Spring AOP 提供了多种匹配切点的方式,可以根据实际需求选择最合适的方式进行使用。在实际场景中,一般使用 AspectJ 表达式是最简单、最直观的方式。
演示 - 切点匹配
根据方法名字匹配
我们如图相匹配bar方法做增强,而不匹配foo方法(AspectJExpressionPointcut 是 Spring AOP 框架中用于封装 AspectJ 表达式的切点实现类):
- 创建 AspectJExpressionPointcut
- 添加表达式 setExpression(); 其中可以指定包名类名方法名等,我们这里指定类bar()
- 调用matches方法判断目标类中的目标方法是否符合上面一步添加的表达式(参数一:目标方法,参数二:目标类)
很明显第一个不匹配,第二个匹配,期望结果为(第一行打印 false 第二行打印 true):
根据方法上加的注解匹配
步骤完全一样,重点看Expression中内容的变化,@annotation() 即为判断是否有注解的表达式,注意里面填的是对应注解的包名加类名
注解我们加在了foo上:
结果如下:
@Transactional 底层匹配实现
对于标注了@Transactional的方法,可以进行事务的开启,在这些功能的底层是否是用上文 根据方法上加的注解匹配的方式进行呢,答案是否定的,因为@Transactional注解不但能加方法上,还能加在类上、接口上等。
代码模拟
这里模拟利用一个抽象父类StaticMethodMatcherPointcut实现其方法matches(参数一:执行的方法对象,参数二:执行方法所在的类),这个方法如果匹配上返回true反之返回false
首先我们优先匹配方法上的,因为方法上有了,就可以直接返回,不用再去看类或者看接口,这里用一个spring 封装好的一个方法接口 MergedAnnotations
注意第二步这里我们在from方法给了第二个参数(参数为搜索策略),这里不给的话是会返回false的,原因是默认为(SearchStrategy.DIRECT)其意思为只会找本类中有没有加该注解,所以我们需要改变一下搜索策略(这里改变策略为在继承数上找)即可,结果如下;
测试代码如下
收获
- 常见 aspectj 切点用法
- aspectj 切点的局限性,实际的 @Transactional 切点实现