Spring - 注解实现AOP的五种通知
2017-04-24 14:13
429 查看
【1】AOP通知
通知是标注有某种注解的简单的 Java 方法.AspectJ 支持 5 种类型的通知注解:
@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行
@AfterRunning:返回通知, 在方法返回结果之后执行
@AfterThrowing: 异常通知, 在方法抛出异常之后
@Around: 环绕通知, 围绕着方法执行
在 Spring 中声明 AspectJ 切面, 需要在 IOC 容器中将切面声明为 Bean 实例.
当在 Spring IOC 容器中初始化 AspectJ 切面之后, Spring IOC 容器就会为那些与 AspectJ 切面相匹配的 Bean 创建代理.
在 AspectJ 注解中, 切面只是一个带有 @Aspect 注解的 Java 类.
【2】注解使用的JAR和xml配置
(1)-要在 spring 应用中使用 AspectJ 注解, 必须在 classpath 下包含 AspectJ 类库: aopalliance.jar、aspectj.weaver.jar 和 spring-aspects.jar
(2)-将 aop Schema 添加到 根元素中.
xmlns:aop="http://www.springframework.org/schema/aop"1
1
(3)-在 Bean 配置文件中定义一个空的 XML 元素
<aop:aspectj-autoproxy>
当 Spring IOC 容器侦测到 Bean 配置文件中的
<aop:aspectj-autoproxy>元素时, 会自动为与 AspectJ 切面匹配的 Bean 创建代理.
<!-- **使Aspect注解起作用,自动为匹配的类生产代理对象** --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 激活组件扫描功能,在包cn.ysh.studio.spring.aop及其子包下面自动扫描通过注解配置的组件 -->
<context:component-scan base-package="cn.ysh.studio.spring.aop"/>1
2
1
2
【3】定义切点表达式方法,使其可以多处使用
定义一个方法,用于声明切入点表达式;一般的,该方法中再不需要添入其他的代码;
使用@Pointcut来声明切入点表达式;
后面的其他通知直接使用方法名来引用当前的切入点表达式
@Pointcut("execution(int com.web.aop.impl.ArithmeticCalculatorImpl.*(int , int ))") public void declareJoinPointExpression() { }1
2
3
4
1
2
3
4
【4】前置通知
前置通知:在方法执行之前执行的通知前置通知使用 @Before 注解, 并将切入点表达式的值作为注解值.
@Before("declareJoinPointExpression()") public void beforMethod(JoinPoint joinPoint){ /*获取方法名*/ String methodName = joinPoint.getSignature().getName(); /*获取方法的参数*/ List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method "+methodName+" begins with"+args); }1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
【5】后置通知
后置通知:在目标方法执行后执行,无论是否抛出异常;后置通知中不能访问目标方法执行后返回的结果;
@After("execution(* com.web.aop.impl.*.*(int , int ))") /*表示该包下所有返回类型的所有类的所有方法*/ public void afterMethod(JoinPoint joinPoint){ /*获取方法名*/ String methodName = joinPoint.getSignature().getName(); /*获取方法的参数*/ List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method "+methodName+" ends with"+args); }1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
【6】返回通知
返回通知 :在方法正常执行后执行;返回通知可以获取目标方法的返回值
在返回通知中, 只要将 returning 属性添加到 @AfterReturning 注解中, 就可以访问连接点的返回值.
该属性的值即为用来传入返回值的参数名称.
必须在通知方法的签名中添加一个同名参数. 在运行时, Spring AOP 会通过这个参数传递返回值.
原始的切点表达式需要出现在 pointcut 属性中
@AfterReturning(pointcut="execution(* com.web.aop.impl.*.*(int , int ))",returning="result") /*表示该包下所有返回类型的所有类的所有方法*/ public void afterReturning(JoinPoint joinPoint ,Object result){ /*获取方法名*/ String methodName = joinPoint.getSignature().getName(); /*获取方法的参数*/ List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method "+methodName+" ends with "+result); }1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
【7】异常通知
异常通知:在方法抛出异常后执行可以访问到异常对象。
且可以指定在出现特定异常对象时,再执行。
只在连接点抛出异常时才执行异常通知
将 throwing 属性添加到 @AfterThrowing 注解中, 也可以访问连接点抛出的异常.
Throwable 是所有错误和异常类的超类. 所以在异常通知方法可以捕获到任何错误和异常.
如果只对某种特殊的异常类型感兴趣, 可以将参数声明为其他异常的参数类型. 然后通知就只在抛出这个类型及其子类的异常时才被执行.
@AfterThrowing(value="execution(* com.web.aop.impl.*.*(int , int ))",throwing="exception") /*表示该包下所有返回类型的所有类的所有方法*/ public void afterThrowing(JoinPoint joinPoint ,Exception exception){ /*获取方法名*/ String methodName = joinPoint.getSignature().getName(); /*获取方法的参数*/ List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method "+methodName+" throws exception :"+exception); }1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
【8】环绕通知
环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点. 甚至可以控制是否执行连接点.环绕通知需要携带ProceedingJoinPoint类型的参数;
环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法;
环绕通知必须有返回值,返回值即为目标方法的返回值 !
对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint .
它是 JoinPoint 的子接口, 允许控制何时执行, 是否执行连接点.
在环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法.
如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行.
注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常
很少使用。。。
@Around("execution(* com.web.aop.impl.*.*(int , int ))") /*表示该包下所有返回类型的所有类的所有方法*/ public Object aroundMethod(ProceedingJoinPoint joinPoint){ System.out.println("This is aroundMethod...."); /*获取方法名*/ String methodName = joinPoint.getSignature().getName(); /*获取方法的参数*/ List<Object> args = Arrays.asList(joinPoint.getArgs()); Object result = null; try { //前置通知 System.out.println("The method "+methodName+" begins with :"+args); result = joinPoint.proceed(); //返回通知 System.out.println(); System.out.println("The method "+methodName+" ends with :"+result); } catch (Throwable e) { // 异常通知 System.out.println("The method "+methodName+" throws exception :"+e); throw new RuntimeException(e); } //后置通知 System.out.println("The method "+methodName+" ends "); return result; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
相关文章推荐
- Spring 4.0 学习日记(8) ---AOP切面注解实现五种通知
- 使用Spring注解方试实现AOP1--前后通知与后置通知
- 基于注解的Spring AOP实现demo(测试通知顺序)
- Spring 注解实现AOP通知
- Spring 通过来AOP 实现前置,环绕,异常通知,注解
- Spring 通过AOP 来实现前置,环绕,异常通知,注解
- Spring 通过来AOP 实现前置,环绕,异常通知,注解(转)
- Spring2.0---- AOP XML实现五种通知
- 使用Spring的注解方式实现AOP的细节
- 使用Spring的注解方式实现AOP
- 一种AOP后置通知的Spring实现案例--密码生成器校验
- springaop术语概述及aop中常见通知的实现(前置,后置,环绕,异常)
- 第五章 Spring进阶-注解方式实现AOP(2)
- 使用Spring注解方试实现AOP2--环绕通知(周围通知)
- spring注解实现AOP
- Spring学习笔记(三)Spring注解方式实现AOP
- Spring的AOP实现之一 --- 用spring编写Spring通知
- 黑马程序员--Spring Aop 面向切面编程,实现前置通知
- springaop术语概述及aop中常见通知的实现(10级学员 庞丽课堂总结)
- 第五章 Spring进阶-注解方式实现AOP(1)