# 《Spring核心技术》第22章:AOP切面型注解实战
作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码地址:https://github.com/binghe001/spring-annotation-book/tree/master/spring-annotation-chapter-22 (opens new window)
沉淀,成长,突破,帮助他人,成就自我。
大家好,我是冰河~~
本章难度:★★★☆☆
本章重点:进一步学习并掌握AOP切面型注解的实战案例,从源码级别彻底掌握切面型注解。
本章目录如下所示:
- 学习指引
- 注解说明
- @EnableAspectJAutoProxy注解
- @Aspect注解
- @Pointcut注解
- @Before注解
- @After注解
- @AfterReturning注解
- @AfterThrowing注解
- @Around
- 使用案例
- 总结
- 思考
- VIP服务
# 一、学习指引
Spring中的AOP切面型注解,你真的彻底了解过吗?
AOP的全称是Aspect Oriented Programming,表示面向切面编程。AOP使用了设计模式中的代理模式,使用AOP可以实现业务逻辑的各个部分分离,降低业务逻辑的耦合性,提高程序的可重用性。在实际项目开发过程中,如果想在业务逻辑中不修改代码的前提下,增加输出的日志信息,此时就可以使用AOP切面实现。
# 二、注解说明
关于Spring中的AOP注解的一点点说明~~
Spring中提供的切面型注解主要有:@EnableAspectJAutoProxy、@Aspect、@Pointcut、@Before、@After、@AfterReturning、@AfterThrowing和@Around。本章,就简单介绍下Spring中提供的切面型注解。
# 2.1 @EnableAspectJAutoProxy注解
@EnableAspectJAutoProxy注解表示开启Spring对基于注解的AOP的支持,如果基于Spring的注解开发程序时,需要使用AOP功能,就需要使用@EnableAspectJAutoProxy注解来开启AOP功能。
@EnableAspectJAutoProxy注解的源码详见:org.springframework.context.annotation.EnableAspectJAutoProxy。
/**
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see org.aspectj.lang.annotation.Aspect
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
/**
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
从源码可以看出,@EnableAspectJAutoProxy注解是从Spring3.1版本开始提供的注解,只能标注到类上,并且使用@Import注解导入了AspectJAutoProxyRegistrar类。在@EnableAspectJAutoProxy注解中只提供了proxyTargetClass和exposeProxy两个属性。
- proxyTargetClass:表示是否基于CGLib进行代理。true:表示基于CGLib进行代理。false:表示基于JDK进行代理。默认值为false。
- exposeProxy:从Spring4.3.1版本开始提供的属性,表示是否对外暴露代理对象。true:对外暴露代理对象,可以通过AopContext进行访问。false:不对外暴露代理对象。默认值为false。
# 2.2 @Aspect注解
@Aspect注解可以将当前类声明为切面类。如果基于Spring注解开发程序时,需要将某个类声明为切面类,就可以使用@Aspect注解。
@Aspect注解的源码详见:org.aspectj.lang.annotation.Aspect。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Aspect {
String value() default "";
}
2
3
4
5
从源码可以看出,@Aspect注解可以标注到类上,并且在@Aspect注解中提供了一个Spring类型的value属性。
- value:指定预处理的切入点表达式。默认的切面类是单例的,如果切面类是一个多例类,则可以使用value属性指定预处理的切入点表达式。除了支持切入点表达式外,也支持使用@Pointcut修饰的方法的全名称。
# 2.3 @Pointcut注解
@Pointcut注解可以指定切入点表达式,在使用Spring注解开发AOP程序时,如果需要执行多个通知,并且使用AOP增强的功能确定的情况下,就可以使用@Pointcut注解将切入点表达式通用化。
@Pointcut注解的源码详见:org.aspectj.lang.annotation.Pointcut。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Pointcut {
String value() default "";
String argNames() default "";
}
2
3
4
5
6
从源码可以看出,@Pointcut注解标注到方法上。并且在@Pointcut注解中提供了两个String类型的属性value和argNames。
- value:表示指定的切入点表达式。
- argNames:表示指定的切入点表达式的参数,参数可以是execution中的,也可以是args中的,并且不使用这个属性也可以获得切入点的方法参数。
# 2.4 @Before注解
@Before注解指定方法为前置通知,指定为前置通知的方法在切入点方法之前执行。在实际开发项目的过程中,如果需要在切入点方法之前执行一些业务逻辑处理,就可以使用@Before注解指定前置通知的方法,让前置通知的方法在切入点方法之前执行。如果在前置通知的方法中需要获取切入点方法中的参数进行处理时,就需要配合使用切入点表达式参数。
@Before注解的源码详见:org.aspectj.lang.annotation.Before。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
String value();
String argNames() default "";
}
2
3
4
5
6
从源码可以看出,@Before注解只能标注到方法上,并且在@Before注解中提供了两个Spring类型的属性,分别是value和argNames。
- value:表示指定切入点表达式,可以是表达式,也可以是表达式的引用。
- argNames:表示指定切入点表达式参数的名称。要求和切入点表达式中的参数名称一致。如果不指定切入点表达式参数的名称,一般情况下也可以获取切入点方法的参数内容。
# 2.5 @After注解
@After注解主要指定最终的通知,如果在实际项目的开发过程中,需要指定最终通知的执行时机,并且需要在切入点方法完成之后执行,无论切入点方法的执行是否抛出异常,都要执行最终的通知方法,就可以使用@After注解标注最终通知的方法。使用@After注解标注的方法也可以用来执行一些清理工作。
@After注解的源码详见:org.aspectj.lang.annotation.After。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface After {
String value();
String argNames() default "";
}
2
3
4
5
6
从源码可以看出,@After注解只能标注到方法上,并且在方法中提供了两个String类型的属性,分别是value和argNames。
- value:表示指定切入点表达式,可以是表达式,也可以是表达式的引用。
- argNames:表示指定切入点表达式参数的名称。要求和切入点表达式中的参数名称一致。如果不指定切入点表达式参数的名称,一般情况下也可以获取切入点方法的参数内容。
# 2.6 @AfterReturning注解
@AfterReturning注解可以配置后置增强切入点方法。被@AfterReturning注解修饰的方法会在切入点方法正常执行之后执行。其实,在实际项目的开发过程中,比如提交事务、记录访问日志等等功能都可以使用@AfterReturning注解的后置通知实现。
@AfterReturning注解的源码详见:org.aspectj.lang.annotation.AfterReturning。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterReturning {
String value() default "";
String pointcut() default "";
String returning() default "";
String argNames() default "";
}
2
3
4
5
6
7
8
从源码可以看出,@AfterReturning注解只能标注到方法上,并且在@AfterReturning注解中提供了四个String类型的属性,分别是value、pointcut、returning和argNames。
- value:表示指定切入点表达式,可以是表达式,也可以是表达式的引用。
- pointcut:同value。
- returning:表示指定切入点方法返回值的变量名称,需要注意的是,指定的名称需要和切入点方法返回值名称一致。
- argNames:表示指定切入点表达式参数的名称。要求和切入点表达式中的参数名称一致。如果不指定切入点表达式参数的名称,一般情况下也可以获取切入点方法的参数内容。
# 2.7 @AfterThrowing注解
@AfterThrowing注解主要是配置异常通知,如果需要在切入点方法执行异常时,执行某些逻辑处理,就可以使用@AfterThrowing注解指定异常通知。
@AfterThrowing注解的源码详见:org.aspectj.lang.annotation.AfterThrowing。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterThrowing {
String value() default "";
String pointcut() default "";
String throwing() default "";
String argNames() default "";
}
2
3
4
5
6
7
8
从源码可以看出,@AfterThrowing注解只能标注到方法上,并且在@AfterThrowing注解中提供了四个String类型的属性,分别是:value、pointcut、throwing和argNames。
- value:表示指定切入点表达式,可以是表达式,也可以是表达式的引用。
- pointcut:同value。
- throwing:表示指定切入点方法执行过程中抛出异常时的异常对象的变量名称,需要和异常变量名称保持一致。
- argNames:表示指定切入点表达式参数的名称。要求和切入点表达式中的参数名称一致。如果不指定切入点表达式参数的名称,一般情况下也可以获取切入点方法的参数内容。
# 2.8 @Around注解
@Around注解用于指定环绕通知,如果在实际项目的开发过程中,需要手动控制增强方法执行的时机,就可以使用@Around注解来实现。
@Around注解的源码详见:org.aspectj.lang.annotation.Around。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Around {
String value();
String argNames() default "";
}
2
3
4
5
6
从源码可以看出,@Around注解只能标注到方法上,并且在@Around方法中提供了两个String类型的属性,分别是value和argNames。
- value:表示指定切入点表达式,可以是表达式,也可以是表达式的引用。
- argNames:表示指定切入点表达式参数的名称。要求和切入点表达式中的参数名称一致。如果不指定切入点表达式参数的名称,一般情况下也可以获取切入点方法的参数内容。
# 三、使用案例
# 查看完整文章
加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码