AbstractAspectJAdvice
的实现类如下:这5个实现类完完整整的对应着我们AspectJ的那5个注解。
AspectJPointcutAdvisor
显然是和AspectJ相关的,使用得很是广泛。注意它和AspectJExpressionPointcutAdvisor的区别。有名字也能看出来,AspectJExpressionPointcutAdvisor和表达式语言的切点相关的,而AspectJPointcutAdvisor是无关的。它哥俩都位于包org.springframework.aop.aspectj里。
public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered { // AbstractAspectJAdvice通知:它的子类看下面截图,就非常清楚了 private final AbstractAspectJAdvice advice; // 可以接受任意的Pointcut,可谓非常的通用(当然也包含切点表达式啦) private final Pointcut pointcut; @Nullable private Integer order; // 只有这一个构造函数,包装一个advice public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; // 然后pointcut根据advice直接给生成了一个。这是AbstractAspectJAdvice#buildSafePointcut的方法 this.pointcut = advice.buildSafePointcut(); } }
InstantiationModelAwarePointcutAdvisor
它是PointcutAdvisor的一个子接口。
// 由SpringAOP顾问包装AspectJ实现的接口 可能具有延迟初始化策略的方面。 // 例如,一个PerThis实例化模型意味着对建议的初始化太慢 public interface InstantiationModelAwarePointcutAdvisor extends PointcutAdvisor { // 该Advisor是否需要懒加载 boolean isLazy(); // 判断此Advisor它所拥有的Advice是否已经初始化了 boolean isAdviceInstantiated(); }
它的唯一实现类:InstantiationModelAwarePointcutAdvisorImpl
// 默认的访问权限,显然是Spring内部自己用的 class InstantiationModelAwarePointcutAdvisorImpl implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable { private static final Advice EMPTY_ADVICE = new Advice() {}; // 和AspectJExpression private final AspectJExpressionPointcut declaredPointcut; .. // 通知方法 private transient Method aspectJAdviceMethod; private final AspectJAdvisorFactory aspectJAdvisorFactory; private final MetadataAwareAspectInstanceFactory aspectInstanceFactory; @Nullable private Advice instantiatedAdvice; @Nullable private Boolean isBeforeAdvice; @Nullable private Boolean isAfterAdvice; ... @Override public boolean isPerInstance() { return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON); } @Override public synchronized Advice getAdvice() { if (this.instantiatedAdvice == null) { this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } return this.instantiatedAdvice; } // advice 由aspectJAdvisorFactory去生产 懒加载的效果 private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) { Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); return (advice != null ? advice : EMPTY_ADVICE); } @Override public boolean isBeforeAdvice() { if (this.isBeforeAdvice == null) { determineAdviceType(); } return this.isBeforeAdvice; } @Override public boolean isAfterAdvice() { if (this.isAfterAdvice == null) { determineAdviceType(); } return this.isAfterAdvice; } // 这里解释根据@Aspect方法上标注的注解,来区分这两个字段的值的 private void determineAdviceType() { AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod); if (aspectJAnnotation == null) { this.isBeforeAdvice = false; this.isAfterAdvice = false; } else { switch (aspectJAnnotation.getAnnotationType()) { case AtAfter: case AtAfterReturning: case AtAfterThrowing: this.isAfterAdvice = true; this.isBeforeAdvice = false; break; case AtAround: case AtPointcut: this.isAfterAdvice = false; this.isBeforeAdvice = false; break; case AtBefore: this.isAfterAdvice = false; this.isBeforeAdvice = true; } } } }
这个Advisor是在Spring解析被 @AspectJ注解注释的类时生成的 Advisor,。
而这个 Advisor中的 Pointcut与Advice都是由ReflectiveAspectJAdvisorFactory 来解析生成的(与之对应的 Advice 是 AspectJMethodBeforeAdvice, AspectJAfterAdvice, AspectJAfterReturningAdvice, AspectJAfterThrowingAdvice, AspectJAroundAdvice,
Pointcut 则是AspectJExpressionPointcut), 解析的步骤是:
自动代理创建器:AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors() ->
Bean工厂相关的Advisor构建器:BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors() ->
ReflectiveAspectJAdvisorFactory.getAdvisors() ->
ReflectiveAspectJAdvisorFactory.getAdvisor() 最终生成了InstantiationModelAwarePointcutAdvisorImpl(当然包括里面的 Pointcut与 advice 也都是由 ReflectiveAspectJAdvisorFactory 解析生成的)
IntroductionAdvisor:引介切面
Spring中有五种增强:BeforeAdvide(前置增强)、AfterAdvice(后置增强)、ThrowsAdvice(异常增强)、RoundAdvice(环绕增强)、IntroductionAdvice(引入增强)
RoundAdvice(环绕增强):就是BeforeAdvide(前置增强)、AfterAdvice(后置增强)的组合使用叫环绕增强。前四种都比较简单。。。
引入增强(Introduction Advice)的概念:一个Java类,没有实现A接口,在不修改Java类的情况下,使其具备A接口的功能。(非常强大有木有,A不需要动代码,就能有别的功能,吊炸天有木有)
IntroductionAdvisor纯粹就是为Introduction而生的。
IntroductionAdvisor 和 PointcutAdvisor接口不同,它仅有一个类过滤器ClassFilter 而没有 MethodMatcher,这是因为 `引介切面 的切点是类级别的,而 Pointcut 的切点是方法级别的(细粒度更细,所以更加常用)。
为了更好的了解IntroductionAdvisor,我先有必要讲解下IntroductionInfo和IntroductionInterceptor;
Introduction可以在不改动目标类定义的情况下,为目标类增加新的属性和行为。
IntroductionInfo:引介信息
IntroductionInfo 接口描述了目标类需要实现的新接口。
// 提供描述引言所需信息的接口 // IntroductionAdvisor必须实现这个接口。若`org.aopalliance.aop.Advice`直接实现了此接口, // 它可议独立的当作introduction来使用而不用依赖IntroductionAdvisor。这种情况下,这个advice可议自描述,不仅提供。。。 public interface IntroductionInfo { //Return the additional interfaces introduced by this Advisor or Advice. // 返回额外给Advisor 或者 advice实现的接口们 Class<?>[] getInterfaces(); }
它的继承结构如下:
IntroductionInterceptor:引介拦截器
在Spring中,为目标对象添加新的属性和行为必须声明相应的接口以及相应的实现。这样,再通过特定的拦截器将新的接口定义以及实现类中的逻辑附加到目标对象上。然后,目标对象(确切的说,是目标对象的代理对象)就拥有了新的状态和行为
这里面介绍这个非常强大的拦截器:IntroductionInterceptor
// IntroductionInterceptor它是对MethodInterceptor的一个扩展,同时他还继承了接口DynamicIntroductionAdvice public interface IntroductionInterceptor extends MethodInterceptor, DynamicIntroductionAdvice { }
DynamicIntroductionAdvice
:
public interface DynamicIntroductionAdvice extends Advice { boolean implementsInterface(Class<?> intf); }
过DynamicIntroductionAdvice,可以界定当前的 IntroductionInterceptor为哪些接口提供相应的拦截功能。通过MethodInterceptor,IntroductionInterceptor 就可以处理新添加的接口上的方法调用了
打个比方
如果把每个目标对象实例看作盒装牛奶生产线上的那一盒盒牛奶的话,那么生产合格证就是新的Introduction逻辑,而introductionInterceptor 就是把这些生产合格证贴到一盒盒牛奶上的那个人。
要对目标对象进行拦截并添加Introduction的逻辑,我们可以直接扩展IntroductionInterceptor,然后在子类的invoke方法中实现所有的拦截逻辑
除非特殊情况下需要直接扩展IntroductionInterceptor,大多数时候,直接使用Spring提供的两个现成的实现类就可以了:DelegatingIntroductionInterceptor 和 DelegatePerTargetObjectIntroductionInterceptor
例子
下面使用一个例子,加深一下对引介增强的了解:
// 定义一个新的行为接口,这个行为准备作用在目标对象上 public interface IOtherInte { void doOther(); } // 自己定义一个IntroductionInterceptor来实现IntroductionInterceptor接口 // 注意:此处也实现了接口IOtherInte(这是类似于增强器部分) 相当于这个interptor目前就只处理 IOtherInte public class SomeInteIntroductionInterceptor implements IntroductionInterceptor, IOtherInte { /** * 判断调用的方法是否为指定类中的方法 * 如果Method代表了一个方法 那么调用它的invoke就相当于执行了它代表的这个方法 */ @Override public Object invoke(MethodInvocation invocation) throws Throwable { if (implementsInterface(invocation.getMethod().getDeclaringClass())) { System.out.println("我是引介增强的方法体~~~invoke"); return invocation.getMethod().invoke(this, invocation.getArguments()); } return invocation.proceed(); } /** * 判断clazz是否为给定接口IOtherBean的实现 */ @Override public boolean implementsInterface(Class clazz) { return clazz.isAssignableFrom(IOtherInte.class); } @Override public void doOther() { System.out.println("给人贴标签 doOther..."); } } // 方法测试 public static void main(String[] args) { ProxyFactory factory = new ProxyFactory(new Person()); factory.setProxyTargetClass(true); // 强制私用CGLIB 以保证我们的Person方法也能正常调用 // 此处采用IntroductionInterceptor 这个引介增强的拦截器 Advice advice = new SomeInteIntroductionInterceptor(); // 切点+通知(注意:此处放的是复合切面) Advisor advisor = new DefaultIntroductionAdvisor((DynamicIntroductionAdvice) advice, IOtherInte.class); //Advisor advisor = new DefaultPointcutAdvisor(cut, advice); factory.addAdvisor(advisor); IOtherInte otherInte = (IOtherInte) factory.getProxy(); otherInte.doOther(); System.out.println("==============================="); // Person本身自己的方法 也得到了保留 Person p = (Person) factory.getProxy(); p.run(); p.say(); } 输出: 我是引介增强的方法体~~~invoke 给人贴标签 doOther... =============================== 我在run... 我在say...