Spring提供了两个额外的Pointcut实现,分别是ComposablePointcut和ControlFlowPointcut,它们提供了所需的灵活性。
使用控制流切入点
由ControlFlowPointcut类实现的Spring控制流切入点类似于许多其他AOP实现中可用的cflow构造,尽管功能上没有那么强大。
本质上,Spring中的控制流切入点适用于类中给定方法或所有方法下的所有方法调用。
制流切入点非常有用,允许仅在另一个上下文中执行某个对象时才有选择地通知它。
但是,请注意,在其他切入点上使用控制流切入点会大大降低性能。
假设有一个事务处理系统,它包含一个TransactionService接口以及一个AccountService接口。
此时,希望应用后置通知,以便当TransactionService.ReverseTransaction()调用AccountService.updateBalance()方法更新账户余额时,将电子邮件通知发送给客户。
但在其他情况下则不会发送电子邮件。在这种情况下,控制流切入点是非常有用的。
使用组合切入点
在某些情况下,可能需要将两个或更多个切入点组合在一起以实现所需的目标。
假设想要切入bean上的所有getter和setter方法。
虽然getter方法有一个切入点,setter方法也有一个切入点,但是没有同时适用于这两种方法的切入点。
当然,可以用新的逻辑创建另一个切入点,但更好的方法是使用ComposablePointcut将两个切入点组合成一个切入点。
ComposablePointcut支持两种方法:union()和intersection()。
默认情况下,ComposablePointcut是通过一个匹配所有类的ClassFilter以及一个匹配所有方法的MethodMatcher来创建的,当然,也可以在构建过程中提供自己的初始ClassFilter和MethodMatcher。
union()和intersection()方法都被重载以接收ClassFilter和MethodMatcher参数。
可以通过传入ClassFilter、MethodMatcher或Pointcut接口的实例来调用ComposablePointcutunion()方法。联合操作的结果是,ComposablePointcut将在其调用链中添加“或”条件,以便与连接点进行匹配。
对于ComposablePointcut.intersection()方法也是如此,但添加的是“和”条件,这意味着如果想要应用通知,ComposablePointcut中的所有ClassFilter、MethodMatcher和Pointcut定义都应该匹配。
可以将其想象为SQL查询中的WHERE子句,其中union()方法类似于“or”运算符,而intersection()方法则类似于“and”运算符。
// 创建一个可组合的切点对象pc,匹配所有类的任一方法
ComposablePointcut pc = new ComposablePointcut(ClassFilter.TRUE, new SingMethodMatcher());
// 将能匹配Talk方法的切点对象合并到pc中
pc.union(new TalkMethodMatcher());
// 将能匹配Rest方法的切点对象与pc进行交集匹配
pc.intersection(new RestMethodMatcher());