Spring AOP(二)--注解方式
本文介绍通过注解@AspectJ实现Spring AOP,这里要重点说明一下这种方式实现时所需的包,因为Aspect是第三方提供的,不包含在spring中,所以不能只导入spring-aop的包,为了安全起见我导入的包有(我是maven方式添加依赖):
步骤如下:
一、创建连接点
spring是方法级别的拦截器,所以连接点就是某个类中的某个方法,从动态代理的角度来看就是将要拦截的方法织入AOP通知。
1⃣️创建一个接口
public interface EmployeeService { public void getEmployeeInfo(Employee employee); public void getEmployeeSex(Employee employee);
}
这个接口中提供了两个方法,后续会用来测试连接点的概念,因为只有将方法织入到AOP才会执行完整的拦截流程。
2⃣️创建接口实现类,增加注解@Component
@Component
public class EmployeeServiceImpl implements EmployeeService { @Override
public void getEmployeeInfo(Employee employee) {
System.out.println("name:" + employee.getUsername() + ";sex:" + employee.getSex());
} @Override
public void getEmployeeSex(Employee employee) {
System.out.println("性别:"+employee.getSex());
}
}
二、创建切面
创建好了连接点之后就可以创建切面了,它就相当于是一个拦截器,在spring中只要使用@Aspect注解一个类,spring ioc容器就会将它视为一个切面处理。
package com.hyc.aop.aspect; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.DeclareParents;
import org.aspectj.lang.annotation.Pointcut; import com.hyc.pojo.Employee; /**
* 定义一个切面
*
* @Aspect 该注解表示这个类就是一个切面了
*/
@Aspect
public class EmployeeAspect { /**
* 定义一个切点,通知aop什么时候启动拦截并织入对应流程
* 注意以下几点:
* 1、方法返回类型* 和方法之间有空格
* 2、在下面的四个方法中引用这个切点时方法名要加括号
* 3、execution正则表达式中的方法就是一个连接点,将代理对象和切面相连,如果不定义这个连接点,则不会将代理对象的方法和切面相连
*/
@Pointcut("execution(* com.hyc.aop.aspect.EmployeeServiceImpl.getEmployeeInfo(..))")
public void getInfo() { } @Before("getInfo()")
public void before() {
System.out.println("before:代理方法执行之前");
} @After("getInfo()")
public void after() {
System.out.println("after:代理方法执行完毕");
} @AfterReturning("getInfo()")
public void afterReturning() {
System.out.println("afterReturning:代理方法执行完毕,执行成功");
} @AfterThrowing("getInfo()")
public void afterThrowing() {
System.out.println("afterThrowing:代理方法执行完毕,执行过程出现异常");
}
}
上面的代码中红色加粗部分所代表的意思如下:
- @Aspect注解:告诉spring,这个类是一个切面;
- @Pointcut注解:定义一个切点,并告诉AOP什么时候启动拦截并织入对应流程;
- @before、@after、@afterReturning、@afterThrowing分别是四种通知,它们可以引用之前定义的切点,也可以有自己的切点;
有必要解释一下定义切点注解@Pointcut中的内容:
@Pointcut("execution(* com.hyc.aop.aspect.EmployeeServiceImpl.getEmployeeInfo(..))")
在上面的注解中,定义了execution的正则表达式,spring是通过这个正则表达式判断是否需要拦截你所定义的方法,即被代理对象的方法。
- execution:代表执行方法的时候会触发;
- *:代表方法的返回类型任意;
- com.hyc.aop.aspect.EmployeeServiceImpl:被代理类的全限定名,注意它和前面的返回类型*之间有一个空格;
- getEmployeeInfo:被拦截方法名称;
- (..):方法中的参数,类型任意;
通过上面的描述,上述注解及内部正则表达式的意思就是:全限定名为com.hyc.aop.aspect.EmployeeServiceImpl的类中的getEmployeeInfo方法被当做一个切点,当程序执行这个方法的时候对它进行拦截,这样就能按照AOP通知的规则把这个方法织入流程中。
三、创建配置类,采用注解java配置
/*
* 定义一个配置类,通过java配置的方式获取切面
*/
@Configuration
@ComponentScan(basePackages= {"com.hyc.aop.aspect","com.hyc.pojo"})
@EnableAspectJAutoProxy //自动代理,代替了动态代理的实现
public class AspectConfig {
//返回一个切面
@Bean
public EmployeeAspect getAspect() {
return new EmployeeAspect();
} }
这个配置就是之前介绍过的注解方式装配bean的配置方法,不过对AOP有效的注解是@EnableAspectJAutoProxy,从字面意思理解它是开启了切面自动代理功能,其实就是启用了AspectJ框架的自动代理,这样spring就会生成一个代理对象,进而使用AOP,其中的getAspect方法是生成了一个切面。
四、测试
完成了上面的配置之后,我就可以进行测试了,测试方法如下:
@Test
public void testAopByConfig() {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AspectConfig.class);
EmployeeService es = (EmployeeService) context.getBean(EmployeeService.class);
Employee employee = (Employee) context.getBean("employee");
es.getEmployeeInfo(employee);
employee = null;
es.getEmployeeInfo(employee);
}
上面的单元测试方法中红色部分:
第四行:首先是获取配置类的上下文,此时已经启动AspectJ的自动代理,并生成了一个切面;
第五行:通过上下文就能生成一个代理对象,如果被代理类有接口则采用jdk动态代理,否则就是CGLIB动态代理;
第七行:测试方法,因为employee不为空,所以可以正常返回,并执行afterReturning方法;
第八、九行:将employee设置为null,执行过程出现异常,所以会执行aferThrowing方法;
查看测试结果:
从上面的运行结果来看,完全符合刚开始的流程图:
1、首先执行before方法;
2、执行被代理对象的方法;
3、执行完被代理对象方法后,不管成功与否都会执行after方法;
4、如果被代理对象的方法正常返回,则执行afterReturning方法,如果返回异常,则执行afterTrowing方法(结果中的afterException是书写错误,其实都一个意思啦
Spring AOP(二)--注解方式的更多相关文章
- spring aop 使用注解方式总结
spring aop的注解方式:和xml的配置方式略有区别,详细如下: 1.首先还是建立需要的切面类:切面类里面定义好切点配置,以及所有的需要实现的通知方法. /** * */ package com ...
- spring AOP自定义注解方式实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- Spring AOP的注解方式实现
spring也支持注解方式实现AOP,相对于配置文件方式,注解配置更加的轻量级,配置.修改更加方便. 1.开启AOP的注解配置方式 <!-- 开启aop属性注解 --> <aop:a ...
- perf4j+spring+aop 配置 注解方式
今天将perf4j基于spring aop方式进入了接入,接入方法还是比较简单.具体配置如下: logback.xml <!--perf4j配置--> <appender name= ...
- Spring AOP(注解方式)
配置文件: xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org ...
- 利用Spring AOP自定义注解解决日志和签名校验
转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先 ...
- 跟着刚哥学习Spring框架--通过注解方式配置Bean(四)
组件扫描:Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件. 特定组件包括: 1.@Component:基本注解,识别一个受Spring管理的组件 2.@Resposit ...
- (转)利用Spring AOP自定义注解解决日志和签名校验
一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: ...
- spring AOP自定义注解 实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
随机推荐
- day24 面向对象设计part1
#!/usr/bin/env python # -*- coding:utf-8 -*- # ----------------------------------------------------- ...
- C++返回引用的需求
1.重载+=操作符返回*this或者某个参数的引用可以方便链式调用,比如C++流操作就是cout<< a << b << c这样的,就是靠不停返回stream的引用 ...
- software database is broken解决办法
ubuntu切换中文时报software database is broken错误. 网上的办法千篇一律,还都没有用.都是去应用中心删除thundbird之类的,啊....... 在终端下执行 sud ...
- linux系统使用小记
1.解决Ubuntu不能正常使用vi的问题.sudo apt-get remove vim-common sudo apt-get install vim 2.备份linux系统,注意,有的优盘单 ...
- 【笔记篇】C#笔记2
返回目录:目录请戳这里~ C#数组 基本概念不提.. int[] a; bool[] b = new bool[10]; float[] c = {0.5, 57.0, 233.3, 12345.67 ...
- Luogu P2458 [SDOI2006]保安站岗(树形dp)
P2458 [SDOI2006]保安站岗 题意 题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下 ...
- JavaScript中定义函数的几种方式
函数的组成:函数名 + 函数体 1.使用function关键字定义函数 -- 具有优先级,优先将function关键字定义的函数优先执行 function functionName(arg0, ar ...
- Georgia and Bob
Georgia and Bob 给出一个严格递增的正整数数列\(\{a_i\}\),每一次操作可以对于其中任意一个数减去一个正整数,但仍然要保证数列的严格递增性,现在两名玩家轮流操作,不能操作的玩家判 ...
- 不用winio直接用c#函数实现模拟键盘
原理来自: http://blog.sina.com.cn/s/blog_71921a8e0100olaw.html /// <summary> /// 导入模拟键盘的方法 /// &l ...
- [ javasript ] javascript中的each遍历!
1.数组中的each var arr = [ "one", "two", "three", "four"]; $.eac ...