Spring入门篇 学习笔记
@AspectJ 的风格类似纯 java 注解的普通 java 类
Spring 可以使用 AspectJ 来做切入点解析
AOP 的运行时仍旧是纯的 Spring AOP, 对 AspectJ 的编译器或者织入无依赖性
Spring 中配置 @AspectJ
对 @AspectJ 支持可以使用 XML 或 Java 风格的配置
1 | <?xml version="1.0" encoding="UTF-8"?> |
确保 AspectJ 的 aspectjweaver.jar (1.6.8或更高版本) 库包含在应用程序的 classpath 中
aspect
@AspectJ 切面使用 @Aspect 注解配置,拥有 @Aspect 的任何 bean 将被 Spring 自动识别并应用
用 @Aspect 注解的类可以有方法和字段,他们也可能包括切入点、通知和引入的声明
@Aspect 注解是不能通过类路径自动检测发现的,所以需要配合使用 @Component 注释或者在 XML 配置 bean
一个类中的 @Aspect 注解标识它为一个切面,并且将自己从自动代理中排除
1 | @Component |
pointcut
一个切入点通过一个普通的方法定义来提供,并且切入点表达式使用 @Pointcut 注解,方法返回类型必须为 void
1 | @Component |
组合 pointcut
切入点表达式可以通过 &&, || 和 ! 进行组合,也可以通过名字引用切入点表达式
通过组合,可以建立更加复杂的切入点表达式
定义良好的 pointcut
AspectJ 是编译期的 AOP
检查代码并匹配连接点与切入点的代价是昂贵的
一个好的切入点应该包括以下几点:
- 选择特定类型的连接点,如:execution, get, set, call, handler
- 确定连接点范围,如:within, withincode
- 匹配上下文信息,如:this, target, @annotation
advice
添加类:
1 | @Service |
添加测试类:
1 | @RunWith(BlockJUnit4ClassRunner.class) |
Before advice
在 MoocAspect 类添加方法:
1 | // @Before("execution(* com.karonda.aop.aspectj.biz.*Biz.*(..))") |
After returning advice
1 | @AfterReturning(pointcut="bizPointcut()", returning="returnValue") |
After throwing advice
1 | @AfterThrowing(pointcut="pointcut()", throwing="e") |
After (finally) advice
最终通知必须准备处理正常和异常两种返回情况,它通常用于释放资源
1 | @After("pointcut()") |
Around advice
1 | @Around("pointcut()") |
advice 扩展
给 advice 传递参数
args
1 | @Before("pointcut() && args(arg)") |
annotation
可以用来判断方法上是否加了某注解或者方法上加的注解对应的值
定义一个注解:
1 | @Retention(RetentionPolicy.RUNTIME) |
添加注解;
1 | @Service |
添加通知:
1 | @Before("pointcut() && @annotation(moocMethod)") |
advice 的参数及泛型
1 | public interface Sample<T>{ |
advice 参数名称
通知和切入点注解有一个额外的 argNames 属性,它可以用来指定所注解的方法的参数名
1 | @Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && annotation(auditable)", argNames="bean,auditable") |
如果第一个参数是 JoinPoint, ProceedingJoinPoint, JoinPoint.StaticPart 那么可以忽略它
1 | @Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && annotation(auditable)", argNames="bean,auditable") |
Introduction
允许一个切面声明一个通知对象实现指定接口,并且提供了一个接口实现类来代表这些对象
introduction 使用 @DeclareParents 进行注解,这个注解用来定义匹配的类型拥有一个新的 parent
1 | @Aspect |
切面实例化模型
perthis 切面通过指定 @Aspect 注解 perthis 子句实现
每个独立的 service 对象执行时都会创建一个切面实例
service 对象的每个方法在第一次执行的时候创建切面实例,切面在 service 对象失效的同时失效
1 | @Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())") |