@

AOP,也就是面向切面编程,它可以将公共的代码抽离出来,动态的织入到目标类、目标方法中,大大提高我们编程的效率,也使程序变得更加优雅。如事务、操作日志等都可以使用AOP实现。这种织入可以是在运行期动态生成代理对象实现,也可以在编译期类加载时期静态织入到代码中。而Spring正是通过第一种方法实现,且在代理类的生成上也有两种方式:JDK Proxy和CGLIB,默认当类实现了接口时使用前者,否则使用后者;另外Spring AOP只能实现对方法的增强。

AOP的术语很多,虽然不清楚术语我们也能很熟练地使用AOP,但是要理解分析源码,术语就需要深刻体会其含义。

  • 增强(Advice):就是我们想要额外增加的功能
  • 目标对象(Target):就是我们想要增强的目标类,如果没有AOP,我们需要在每个目标对象中实现日志、事务管理等非业务逻辑
  • 连接点(JoinPoint):程序执行时的特定时机,如方法执行前、后以及抛出异常后等等。
  • 切点(Pointcut):连接点的导航,我们如何找到目标对象呢?切点的作用就在于此,在Spring中就是匹配表达式。
  • 引介(Introduction):引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过AOP的引介功能,我们可以动态地为该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。
  • 织入(Weaving):即如何将增强添加到目标对象的连接点上,有动态(运行期生成代理)、静态(编译期、类加载时期)两种方式。
  • 代理(Proxy):目标对象被织入增强后,就会产生一个代理对象,该对象可能是和原对象实现了同样的一个接口(JDK),也可能是原对象的子类(CGLIB)。
  • 切面(Aspect、Advisor):切面由切点和增强组成,包含了这两者的定义。

在熟悉了AOP术语后,下面就来看看Spring是如何创建代理对象的,是否还记得上一篇提到的AOP的入口呢?在AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsAfterInitialization方法中循环调用了BeanPostProcessorpostProcessAfterInitialization方法,其中一个就是我们创建代理对象的入口。这里是Bean实例化完成去创建代理对象,理所当然应该这样,但实际上在Bean实例化之前调用了一个resolveBeforeInstantiation方法,这里实际上我们也是有机会可以提前创建代理对象的,这里放到最后来分析,先来看主入口,进入到AbstractAutoProxyCreator类中:

  1. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  2. if (bean != null) {
  3. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  4. if (!this.earlyProxyReferences.contains(cacheKey)) {
  5. return wrapIfNecessary(bean, beanName, cacheKey);
  6. }
  7. }
  8. return bean;
  9. }
  10. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  11. //创建当前bean的代理,如果这个bean有advice的话,重点看
  12. // Create proxy if we have advice.
  13. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  14. //如果有切面,则生成该bean的代理
  15. if (specificInterceptors != DO_NOT_PROXY) {
  16. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  17. //把被代理对象bean实例封装到SingletonTargetSource对象中
  18. Object proxy = createProxy(
  19. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  20. this.proxyTypes.put(cacheKey, proxy.getClass());
  21. return proxy;
  22. }
  23. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  24. return bean;
  25. }

先从缓存中拿,没有则调用wrapIfNecessary方法创建。在这个方法里面主要看两个地方:getAdvicesAndAdvisorsForBeancreateProxy。简单一句话概括就是先扫描后创建,问题是扫描什么呢?你可以先结合上面的概念思考下,换你会怎么做。进入到子类AbstractAdvisorAutoProxyCreatorgetAdvicesAndAdvisorsForBean方法中:

  1. protected Object[] getAdvicesAndAdvisorsForBean(
  2. Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
  3. //找到合格的切面
  4. List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  5. if (advisors.isEmpty()) {
  6. return DO_NOT_PROXY;
  7. }
  8. return advisors.toArray();
  9. }
  10. protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  11. //找到候选的切面,其实就是一个寻找有@Aspectj注解的过程,把工程中所有有这个注解的类封装成Advisor返回
  12. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  13. //判断候选的切面是否作用在当前beanClass上面,就是一个匹配过程。现在就是一个匹配
  14. List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  15. extendAdvisors(eligibleAdvisors);
  16. if (!eligibleAdvisors.isEmpty()) {
  17. //对有@Order@Priority进行排序
  18. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  19. }
  20. return eligibleAdvisors;
  21. }

findEligibleAdvisors方法中可以看到有两个步骤,第一先找到所有的切面,即扫描所有带有@Aspect注解的类,并将其中的切点(表达式)增强封装为切面,扫描完成后,自然是要判断哪些切面能够连接到当前Bean实例上。下面一步步来分析,首先是扫描过程,进入到AnnotationAwareAspectJAutoProxyCreator类中:

  1. protected List<Advisor> findCandidateAdvisors() {
  2. // 先通过父类AbstractAdvisorAutoProxyCreator扫描,这里不重要
  3. List<Advisor> advisors = super.findCandidateAdvisors();
  4. // 主要看这里
  5. if (this.aspectJAdvisorsBuilder != null) {
  6. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  7. }
  8. return advisors;
  9. }

这里委托给了BeanFactoryAspectJAdvisorsBuilderAdapter类,并调用其父类的buildAspectJAdvisors方法创建切面对象:

  1. public List<Advisor> buildAspectJAdvisors() {
  2. List<String> aspectNames = this.aspectBeanNames;
  3. if (aspectNames == null) {
  4. synchronized (this) {
  5. aspectNames = this.aspectBeanNames;
  6. if (aspectNames == null) {
  7. List<Advisor> advisors = new ArrayList<>();
  8. aspectNames = new ArrayList<>();
  9. //获取spring容器中的所有bean的名称BeanName
  10. String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  11. this.beanFactory, Object.class, true, false);
  12. for (String beanName : beanNames) {
  13. if (!isEligibleBean(beanName)) {
  14. continue;
  15. }
  16. Class<?> beanType = this.beanFactory.getType(beanName);
  17. if (beanType == null) {
  18. continue;
  19. }
  20. //判断类上是否有@Aspect注解
  21. if (this.advisorFactory.isAspect(beanType)) {
  22. aspectNames.add(beanName);
  23. AspectMetadata amd = new AspectMetadata(beanType, beanName);
  24. if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
  25. // 当@Aspect的value属性为""时才会进入到这里
  26. // 创建获取有@Aspect注解类的实例工厂,负责获取有@Aspect注解类的实例
  27. MetadataAwareAspectInstanceFactory factory =
  28. new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
  29. //创建切面advisor对象
  30. List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
  31. if (this.beanFactory.isSingleton(beanName)) {
  32. this.advisorsCache.put(beanName, classAdvisors);
  33. }
  34. else {
  35. this.aspectFactoryCache.put(beanName, factory);
  36. }
  37. advisors.addAll(classAdvisors);
  38. }
  39. else {
  40. MetadataAwareAspectInstanceFactory factory =
  41. new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
  42. this.aspectFactoryCache.put(beanName, factory);
  43. advisors.addAll(this.advisorFactory.getAdvisors(factory));
  44. }
  45. }
  46. }
  47. this.aspectBeanNames = aspectNames;
  48. return advisors;
  49. }
  50. }
  51. }
  52. return advisors;
  53. }

这个方法里面首先从IOC中拿到所有Bean的名称,并循环判断该类上是否带有@Aspect注解,如果有则将BeanName和Bean的Class类型封装到BeanFactoryAspectInstanceFactory中,并调用ReflectiveAspectJAdvisorFactory.getAdvisors创建切面对象:

  1. public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
  2. //从工厂中获取有@Aspect注解的类Class
  3. Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
  4. //从工厂中获取有@Aspect注解的类的名称
  5. String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
  6. validate(aspectClass);
  7. // 创建工厂的装饰类,获取实例只会获取一次
  8. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
  9. new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
  10. List<Advisor> advisors = new ArrayList<>();
  11. //这里循环没有@Pointcut注解的方法
  12. for (Method method : getAdvisorMethods(aspectClass)) {
  13. //非常重要重点看看
  14. Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
  15. if (advisor != null) {
  16. advisors.add(advisor);
  17. }
  18. }
  19. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
  20. Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
  21. advisors.add(0, instantiationAdvisor);
  22. }
  23. //判断属性上是否有引介注解,这里可以不看
  24. for (Field field : aspectClass.getDeclaredFields()) {
  25. //判断属性上是否有DeclareParents注解,如果有返回切面
  26. Advisor advisor = getDeclareParentsAdvisor(field);
  27. if (advisor != null) {
  28. advisors.add(advisor);
  29. }
  30. }
  31. return advisors;
  32. }
  33. private List<Method> getAdvisorMethods(Class<?> aspectClass) {
  34. final List<Method> methods = new ArrayList<>();
  35. ReflectionUtils.doWithMethods(aspectClass, method -> {
  36. // Exclude pointcuts
  37. if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
  38. methods.add(method);
  39. }
  40. });
  41. methods.sort(METHOD_COMPARATOR);
  42. return methods;
  43. }

根据Aspect的Class拿到所有不带@Pointcut注解的方法对象(为什么是不带@Pointcut注解的方法?仔细想想不难理解),另外要注意这里对method进行了排序,看看这个METHOD_COMPARATOR比较器:

  1. private static final Comparator<Method> METHOD_COMPARATOR;
  2. static {
  3. Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
  4. new InstanceComparator<>(
  5. Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
  6. (Converter<Method, Annotation>) method -> {
  7. AspectJAnnotation<?> annotation =
  8. AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
  9. return (annotation != null ? annotation.getAnnotation() : null);
  10. });
  11. Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
  12. METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
  13. }

关注InstanceComparator构造函数参数,记住它们的顺序,这就是AOP链式调用中同一个@Aspect类中Advice的执行顺序。接着往下看,在getAdvisors方法中循环获取到的methods,分别调用getAdvisor方法,也就是根据方法逐个去创建切面:

  1. public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
  2. int declarationOrderInAspect, String aspectName) {
  3. validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
  4. //获取pointCut对象,最重要的是从注解中获取表达式
  5. AspectJExpressionPointcut expressionPointcut = getPointcut(
  6. candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
  7. if (expressionPointcut == null) {
  8. return null;
  9. }
  10. //创建Advisor切面类,这才是真正的切面类,一个切面类里面肯定要有1、pointCut 2、advice
  11. //这里pointCut是expressionPointcut, advice 增强方法是 candidateAdviceMethod
  12. return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
  13. this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
  14. }
  15. private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
  16. Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
  17. private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
  18. //从候选的增强方法里面 candidateAdviceMethod 找有有注解
  19. //Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
  20. //并把注解信息封装成AspectJAnnotation对象
  21. AspectJAnnotation<?> aspectJAnnotation =
  22. AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
  23. if (aspectJAnnotation == null) {
  24. return null;
  25. }
  26. //创建一个PointCut类,并且把前面从注解里面解析的表达式设置进去
  27. AspectJExpressionPointcut ajexp =
  28. new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
  29. ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
  30. if (this.beanFactory != null) {
  31. ajexp.setBeanFactory(this.beanFactory);
  32. }
  33. return ajexp;
  34. }

之前就说过切面的定义,是切点和增强的组合,所以这里首先通过getPointcut获取到注解对象,然后new了一个Pointcut对象,并将表达式设置进去。然后在getAdvisor方法中最后new了一个InstantiationModelAwarePointcutAdvisorImpl对象:

  1. public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
  2. Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
  3. MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
  4. this.declaredPointcut = declaredPointcut;
  5. this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
  6. this.methodName = aspectJAdviceMethod.getName();
  7. this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
  8. this.aspectJAdviceMethod = aspectJAdviceMethod;
  9. this.aspectJAdvisorFactory = aspectJAdvisorFactory;
  10. this.aspectInstanceFactory = aspectInstanceFactory;
  11. this.declarationOrder = declarationOrder;
  12. this.aspectName = aspectName;
  13. if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
  14. // Static part of the pointcut is a lazy type.
  15. Pointcut preInstantiationPointcut = Pointcuts.union(
  16. aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
  17. // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
  18. // If it's not a dynamic pointcut, it may be optimized out
  19. // by the Spring AOP infrastructure after the first evaluation.
  20. this.pointcut = new PerTargetInstantiationModelPointcut(
  21. this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
  22. this.lazy = true;
  23. }
  24. else {
  25. // A singleton aspect.
  26. this.pointcut = this.declaredPointcut;
  27. this.lazy = false;
  28. //这个方法重点看看,创建advice对象
  29. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
  30. }
  31. }

这个就是我们的切面类,在其构造方法的最后通过instantiateAdvice创建了Advice对象。注意这里传进来的declarationOrder参数,它就是循环method时的序号,其作用就是赋值给这里的declarationOrder属性以及Advice的declarationOrder属性,在后面排序时就会通过这个序号来比较,因此Advice的执行顺序是固定的,至于为什么要固定,后面分析完AOP链式调用过程自然就明白了。

  1. public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
  2. MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
  3. //获取有@Aspect注解的类
  4. Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
  5. validate(candidateAspectClass);
  6. //找到candidateAdviceMethod方法上面的注解,并且包装成AspectJAnnotation对象,这个对象中就有注解类型
  7. AspectJAnnotation<?> aspectJAnnotation =
  8. AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
  9. if (aspectJAnnotation == null) {
  10. return null;
  11. }
  12. AbstractAspectJAdvice springAdvice;
  13. //根据不同的注解类型创建不同的advice类实例
  14. switch (aspectJAnnotation.getAnnotationType()) {
  15. case AtPointcut:
  16. if (logger.isDebugEnabled()) {
  17. logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
  18. }
  19. return null;
  20. case AtAround:
  21. //实现了MethodInterceptor接口
  22. springAdvice = new AspectJAroundAdvice(
  23. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  24. break;
  25. case AtBefore:
  26. //实现了MethodBeforeAdvice接口,没有实现MethodInterceptor接口
  27. springAdvice = new AspectJMethodBeforeAdvice(
  28. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  29. break;
  30. case AtAfter:
  31. //实现了MethodInterceptor接口
  32. springAdvice = new AspectJAfterAdvice(
  33. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  34. break;
  35. case AtAfterReturning:
  36. //实现了AfterReturningAdvice接口,没有实现MethodInterceptor接口
  37. springAdvice = new AspectJAfterReturningAdvice(
  38. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  39. AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
  40. if (StringUtils.hasText(afterReturningAnnotation.returning())) {
  41. springAdvice.setReturningName(afterReturningAnnotation.returning());
  42. }
  43. break;
  44. case AtAfterThrowing:
  45. //实现了MethodInterceptor接口
  46. springAdvice = new AspectJAfterThrowingAdvice(
  47. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  48. AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
  49. if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
  50. springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
  51. }
  52. break;
  53. default:
  54. throw new UnsupportedOperationException(
  55. "Unsupported advice type on method: " + candidateAdviceMethod);
  56. }
  57. // Now to configure the advice...
  58. springAdvice.setAspectName(aspectName);
  59. springAdvice.setDeclarationOrder(declarationOrder);
  60. String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
  61. if (argNames != null) {
  62. springAdvice.setArgumentNamesFromStringArray(argNames);
  63. }
  64. //计算argNames和类型的对应关系
  65. springAdvice.calculateArgumentBindings();
  66. return springAdvice;
  67. }

这里逻辑很清晰,就是拿到方法上的注解类型,根据类型创建不同的增强Advice对象:AspectJAroundAdvice、AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice。完成之后通过calculateArgumentBindings方法进行参数绑定,感兴趣的可自行研究。这里主要看看几个Advice的继承体系:
在这里插入图片描述
可以看到有两个Advice是没有实现MethodInterceptor接口的:AspectJMethodBeforeAdvice和AspectJAfterReturningAdvice。而MethodInterceptor有一个invoke方法,这个方法就是链式调用的核心方法,但那两个没有实现该方法的Advice怎么处理呢?稍后会分析。
到这里切面对象就创建完成了,接下来就是判断当前创建的Bean实例是否和这些切面匹配以及对切面排序。匹配过程比较复杂,对理解主流程也没什么帮助,所以这里就不展开分析,感兴趣的自行分析(AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply())。下面看看排序的过程,回到AbstractAdvisorAutoProxyCreator.findEligibleAdvisors方法:

  1. protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  2. //找到候选的切面,其实就是一个寻找有@Aspectj注解的过程,把工程中所有有这个注解的类封装成Advisor返回
  3. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  4. //判断候选的切面是否作用在当前beanClass上面,就是一个匹配过程。。现在就是一个匹配
  5. List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  6. extendAdvisors(eligibleAdvisors);
  7. if (!eligibleAdvisors.isEmpty()) {
  8. //对有@Order@Priority进行排序
  9. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  10. }
  11. return eligibleAdvisors;
  12. }

sortAdvisors方法就是排序,但这个方法有两个实现:当前类AbstractAdvisorAutoProxyCreator和子类AspectJAwareAdvisorAutoProxyCreator,应该走哪个呢?
在这里插入图片描述
通过类图我们可以肯定是进入的AspectJAwareAdvisorAutoProxyCreator类,因为AnnotationAwareAspectJAutoProxyCreator的父类是它。

  1. protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
  2. List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
  3. for (Advisor element : advisors) {
  4. partiallyComparableAdvisors.add(
  5. new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
  6. }
  7. List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
  8. if (sorted != null) {
  9. List<Advisor> result = new ArrayList<>(advisors.size());
  10. for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
  11. result.add(pcAdvisor.getAdvisor());
  12. }
  13. return result;
  14. }
  15. else {
  16. return super.sortAdvisors(advisors);
  17. }
  18. }

这里排序主要是委托给PartialOrder进行的,而在此之前将所有的切面都封装成了PartiallyComparableAdvisorHolder对象,注意传入的DEFAULT_PRECEDENCE_COMPARATOR参数,这个就是比较器对象:

  1. private static final Comparator<Advisor> DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();

所以我们直接看这个比较器的compare方法:

  1. public int compare(Advisor o1, Advisor o2) {
  2. int advisorPrecedence = this.advisorComparator.compare(o1, o2);
  3. if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
  4. advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
  5. }
  6. return advisorPrecedence;
  7. }
  8. private final Comparator<? super Advisor> advisorComparator;
  9. public AspectJPrecedenceComparator() {
  10. this.advisorComparator = AnnotationAwareOrderComparator.INSTANCE;
  11. }

第一步先通过AnnotationAwareOrderComparator去比较,点进去看可以发现是对实现了PriorityOrderedOrdered接口以及标记了PriorityOrder注解的非同一个@Aspect类中的切面进行排序。这个和之前分析BeanFacotryPostProcessor类是一样的原理。而对同一个@Aspect类中的切面排序主要是comparePrecedenceWithinAspect方法:

  1. private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
  2. boolean oneOrOtherIsAfterAdvice =
  3. (AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
  4. int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);
  5. if (oneOrOtherIsAfterAdvice) {
  6. // the advice declared last has higher precedence
  7. if (adviceDeclarationOrderDelta < 0) {
  8. // advice1 was declared before advice2
  9. // so advice1 has lower precedence
  10. return LOWER_PRECEDENCE;
  11. }
  12. else if (adviceDeclarationOrderDelta == 0) {
  13. return SAME_PRECEDENCE;
  14. }
  15. else {
  16. return HIGHER_PRECEDENCE;
  17. }
  18. }
  19. else {
  20. // the advice declared first has higher precedence
  21. if (adviceDeclarationOrderDelta < 0) {
  22. // advice1 was declared before advice2
  23. // so advice1 has higher precedence
  24. return HIGHER_PRECEDENCE;
  25. }
  26. else if (adviceDeclarationOrderDelta == 0) {
  27. return SAME_PRECEDENCE;
  28. }
  29. else {
  30. return LOWER_PRECEDENCE;
  31. }
  32. }
  33. }
  34. private int getAspectDeclarationOrder(Advisor anAdvisor) {
  35. AspectJPrecedenceInformation precedenceInfo =
  36. AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor);
  37. if (precedenceInfo != null) {
  38. return precedenceInfo.getDeclarationOrder();
  39. }
  40. else {
  41. return 0;
  42. }
  43. }

这里就是通过precedenceInfo.getDeclarationOrder拿到在创建InstantiationModelAwarePointcutAdvisorImpl对象时设置的declarationOrder属性,这就验证了之前的说法(实际上这里排序过程非常复杂,不是简单的按照这个属性进行排序)。
当上面的一切都进行完成后,就该创建代理对象了,回到AbstractAutoProxyCreator.wrapIfNecessary,看关键部分代码:

  1. //如果有切面,则生成该bean的代理
  2. if (specificInterceptors != DO_NOT_PROXY) {
  3. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  4. //把被代理对象bean实例封装到SingletonTargetSource对象中
  5. Object proxy = createProxy(
  6. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  7. this.proxyTypes.put(cacheKey, proxy.getClass());
  8. return proxy;
  9. }

注意这里将被代理对象封装成了一个SingletonTargetSource对象,它是TargetSource的实现类。

  1. protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
  2. @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  3. if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
  4. AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  5. }
  6. //创建代理工厂
  7. ProxyFactory proxyFactory = new ProxyFactory();
  8. proxyFactory.copyFrom(this);
  9. if (!proxyFactory.isProxyTargetClass()) {
  10. if (shouldProxyTargetClass(beanClass, beanName)) {
  11. //proxyTargetClass 是否对类进行代理,而不是对接口进行代理,设置为true时,使用CGLib代理。
  12. proxyFactory.setProxyTargetClass(true);
  13. }
  14. else {
  15. evaluateProxyInterfaces(beanClass, proxyFactory);
  16. }
  17. }
  18. //把advice类型的增强包装成advisor切面
  19. Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  20. proxyFactory.addAdvisors(advisors);
  21. proxyFactory.setTargetSource(targetSource);
  22. customizeProxyFactory(proxyFactory);
  23. ////用来控制代理工厂被配置后,是否还允许修改代理的配置,默认为false
  24. proxyFactory.setFrozen(this.freezeProxy);
  25. if (advisorsPreFiltered()) {
  26. proxyFactory.setPreFiltered(true);
  27. }
  28. //获取代理实例
  29. return proxyFactory.getProxy(getProxyClassLoader());
  30. }

这里通过ProxyFactory对象去创建代理实例,这是工厂模式的体现,但在创建代理对象之前还有几个准备动作:需要判断是JDK代理还是CGLIB代理以及通过buildAdvisors方法将扩展的Advice封装成Advisor切面。准备完成则通过getProxy创建代理对象:

  1. public Object getProxy(@Nullable ClassLoader classLoader) {
  2. //根据目标对象是否有接口来判断采用什么代理方式,cglib代理还是jdk动态代理
  3. return createAopProxy().getProxy(classLoader);
  4. }
  5. protected final synchronized AopProxy createAopProxy() {
  6. if (!this.active) {
  7. activate();
  8. }
  9. return getAopProxyFactory().createAopProxy(this);
  10. }
  11. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  12. if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  13. Class<?> targetClass = config.getTargetClass();
  14. if (targetClass == null) {
  15. throw new AopConfigException("TargetSource cannot determine target class: " +
  16. "Either an interface or a target is required for proxy creation.");
  17. }
  18. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
  19. return new JdkDynamicAopProxy(config);
  20. }
  21. return new ObjenesisCglibAopProxy(config);
  22. }
  23. else {
  24. return new JdkDynamicAopProxy(config);
  25. }
  26. }

首先通过配置拿到对应的代理类:ObjenesisCglibAopProxy和JdkDynamicAopProxy,然后再通过getProxy创建Bean的代理,这里以JdkDynamicAopProxy为例:

  1. public Object getProxy(@Nullable ClassLoader classLoader) {
  2. //advised是代理工厂对象
  3. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  4. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  5. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  6. }

这里的代码你应该不陌生了,就是JDK的原生API,newProxyInstance方法传入的InvocationHandler对象是this,因此,最终AOP代理的调用就是从该类中的invoke方法开始。至此,代理对象的创建就完成了,下面来看下整个过程的时序图:
在这里插入图片描述

代理对象的创建过程整体来说并不复杂,首先找到所有带有@Aspect注解的类,并获取其中没有@Pointcut注解的方法,循环创建切面,而创建切面需要切点增强两个元素,其中切点可简单理解为我们写的表达式,增强则是根据@Before、@Around、@After等注解创建的对应的Advice类。切面创建好后则需要循环判断哪些切面能对当前的Bean实例的方法进行增强并排序,最后通过ProxyFactory创建代理对象。

熟悉JDK动态代理的都知道通过代理对象调用方法时,会进入到InvocationHandler对象的invoke方法,所以我们直接从JdkDynamicAopProxy的这个方法开始:

  1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  2. MethodInvocation invocation;
  3. Object oldProxy = null;
  4. boolean setProxyContext = false;
  5. //从代理工厂中拿到TargetSource对象,该对象包装了被代理实例bean
  6. TargetSource targetSource = this.advised.targetSource;
  7. Object target = null;
  8. try {
  9. //被代理对象的equals方法和hashCode方法是不能被代理的,不会走切面
  10. .......
  11. Object retVal;
  12. // 可以从当前线程中拿到代理对象
  13. if (this.advised.exposeProxy) {
  14. // Make invocation available if necessary.
  15. oldProxy = AopContext.setCurrentProxy(proxy);
  16. setProxyContext = true;
  17. }
  18. //这个target就是被代理实例
  19. target = targetSource.getTarget();
  20. Class<?> targetClass = (target != null ? target.getClass() : null);
  21. //从代理工厂中拿过滤器链 Object是一个MethodInterceptor类型的对象,其实就是一个advice对象
  22. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  23. //如果该方法没有执行链,则说明这个方法不需要被拦截,则直接反射调用
  24. if (chain.isEmpty()) {
  25. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  26. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  27. }
  28. else {
  29. invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  30. retVal = invocation.proceed();
  31. }
  32. // Massage return value if necessary.
  33. Class<?> returnType = method.getReturnType();
  34. if (retVal != null && retVal == target &&
  35. returnType != Object.class && returnType.isInstance(proxy) &&
  36. !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
  37. retVal = proxy;
  38. }
  39. return retVal;
  40. }
  41. finally {
  42. if (target != null && !targetSource.isStatic()) {
  43. // Must have come from TargetSource.
  44. targetSource.releaseTarget(target);
  45. }
  46. if (setProxyContext) {
  47. // Restore old proxy.
  48. AopContext.setCurrentProxy(oldProxy);
  49. }
  50. }
  51. }

这段代码比较长,我删掉了不关键的地方。首先来看this.advised.exposeProxy这个属性,这在@EnableAspectJAutoProxy注解中可以配置,当为true时,会将该代理对象设置到当前线程的ThreadLocal对象中,这样就可以通过AopContext.currentProxy拿到代理对象。这个有什么用呢?我相信有经验的Java开发都遇到过这样一个BUG,在Service实现类中调用本类中的另一个方法时,事务不会生效,这是因为直接通过this调用就不会调用到代理对象的方法,而是原对象的,所以事务切面就没有生效。因此这种情况下就可以从当前线程的ThreadLocal对象拿到代理对象,不过实际上直接使用@Autowired注入自己本身也可以拿到代理对象。
接下来就是通过getInterceptorsAndDynamicInterceptionAdvice拿到执行链,看看具体做了哪些事情:

  1. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
  2. Advised config, Method method, @Nullable Class<?> targetClass) {
  3. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  4. //从代理工厂中获得该被代理类的所有切面advisor,config就是代理工厂对象
  5. Advisor[] advisors = config.getAdvisors();
  6. List<Object> interceptorList = new ArrayList<>(advisors.length);
  7. Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
  8. Boolean hasIntroductions = null;
  9. for (Advisor advisor : advisors) {
  10. //大部分走这里
  11. if (advisor instanceof PointcutAdvisor) {
  12. // Add it conditionally.
  13. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
  14. //如果切面的pointCut和被代理对象是匹配的,说明是切面要拦截的对象
  15. if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
  16. MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
  17. boolean match;
  18. if (mm instanceof IntroductionAwareMethodMatcher) {
  19. if (hasIntroductions == null) {
  20. hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
  21. }
  22. match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
  23. }
  24. else {
  25. //接下来判断方法是否是切面pointcut需要拦截的方法
  26. match = mm.matches(method, actualClass);
  27. }
  28. //如果类和方法都匹配
  29. if (match) {
  30. //获取到切面advisor中的advice,并且包装成MethodInterceptor类型的对象
  31. MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
  32. if (mm.isRuntime()) {
  33. for (MethodInterceptor interceptor : interceptors) {
  34. interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
  35. }
  36. }
  37. else {
  38. interceptorList.addAll(Arrays.asList(interceptors));
  39. }
  40. }
  41. }
  42. }
  43. //如果是引介切面
  44. else if (advisor instanceof IntroductionAdvisor) {
  45. IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
  46. if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
  47. Interceptor[] interceptors = registry.getInterceptors(advisor);
  48. interceptorList.addAll(Arrays.asList(interceptors));
  49. }
  50. }
  51. else {
  52. Interceptor[] interceptors = registry.getInterceptors(advisor);
  53. interceptorList.addAll(Arrays.asList(interceptors));
  54. }
  55. }
  56. return interceptorList;
  57. }

这也是个长方法,看关键的部分,因为之前我们创建的基本上都是InstantiationModelAwarePointcutAdvisorImpl对象,该类是PointcutAdvisor的实现类,所以会进入第一个if判断里,这里首先进行匹配,看切点当前对象以及该对象的哪些方法匹配,如果能匹配上,则调用getInterceptors获取执行链:

  1. private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
  2. public DefaultAdvisorAdapterRegistry() {
  3. registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
  4. registerAdvisorAdapter(new AfterReturningAdviceAdapter());
  5. registerAdvisorAdapter(new ThrowsAdviceAdapter());
  6. }
  7. public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
  8. List<MethodInterceptor> interceptors = new ArrayList<>(3);
  9. Advice advice = advisor.getAdvice();
  10. //如果是MethodInterceptor类型的,如:AspectJAroundAdvice
  11. //AspectJAfterAdvice
  12. //AspectJAfterThrowingAdvice
  13. if (advice instanceof MethodInterceptor) {
  14. interceptors.add((MethodInterceptor) advice);
  15. }
  16. //处理 AspectJMethodBeforeAdvice AspectJAfterReturningAdvice
  17. for (AdvisorAdapter adapter : this.adapters) {
  18. if (adapter.supportsAdvice(advice)) {
  19. interceptors.add(adapter.getInterceptor(advisor));
  20. }
  21. }
  22. if (interceptors.isEmpty()) {
  23. throw new UnknownAdviceTypeException(advisor.getAdvice());
  24. }
  25. return interceptors.toArray(new MethodInterceptor[0]);
  26. }

这里我们可以看到如果是MethodInterceptor的实现类,则直接添加到链中,如果不是,则需要通过适配器去包装后添加,刚好这里有MethodBeforeAdviceAdapterAfterReturningAdviceAdapter两个适配器对应上文两个没有实现MethodInterceptor接口的类。最后将Interceptors返回。

  1. if (chain.isEmpty()) {
  2. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  3. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  4. }
  5. else {
  6. // We need to create a method invocation...
  7. invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  8. // Proceed to the joinpoint through the interceptor chain.
  9. retVal = invocation.proceed();
  10. }

返回到invoke方法后,如果执行链为空,说明该方法不需要被增强,所以直接反射调用原对象的方法(注意传入的是TargetSource封装的被代理对象);反之,则通过ReflectiveMethodInvocation类进行链式调用,关键方法就是proceed

  1. private int currentInterceptorIndex = -1;
  2. public Object proceed() throws Throwable {
  3. //如果执行链中的advice全部执行完,则直接调用joinPoint方法,就是被代理方法
  4. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
  5. return invokeJoinpoint();
  6. }
  7. Object interceptorOrInterceptionAdvice =
  8. this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  9. if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
  10. InterceptorAndDynamicMethodMatcher dm =
  11. (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
  12. Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
  13. if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
  14. return dm.interceptor.invoke(this);
  15. }
  16. else {
  17. return proceed();
  18. }
  19. }
  20. else {
  21. //调用MethodInterceptor中的invoke方法
  22. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
  23. }
  24. }

这个方法的核心就在两个地方:invokeJoinpointinterceptorOrInterceptionAdvice.invoke(this)。当增强方法调用完后就会通过前者调用到被代理的方法,否则则是依次调用Interceptorinvoke方法。下面就分别看看每个Interceptor是怎么实现的。

  • AspectJAroundAdvice
  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. if (!(mi instanceof ProxyMethodInvocation)) {
  3. throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
  4. }
  5. ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
  6. ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
  7. JoinPointMatch jpm = getJoinPointMatch(pmi);
  8. return invokeAdviceMethod(pjp, jpm, null, null);
  9. }
  • MethodBeforeAdviceInterceptor -> AspectJMethodBeforeAdvice
  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
  3. return mi.proceed();
  4. }
  5. public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
  6. invokeAdviceMethod(getJoinPointMatch(), null, null);
  7. }
  • AspectJAfterAdvice
  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. try {
  3. return mi.proceed();
  4. }
  5. finally {
  6. invokeAdviceMethod(getJoinPointMatch(), null, null);
  7. }
  8. }
  • AfterReturningAdviceInterceptor -> AspectJAfterReturningAdvice
  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. Object retVal = mi.proceed();
  3. this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
  4. return retVal;
  5. }
  6. public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
  7. if (shouldInvokeOnReturnValueOf(method, returnValue)) {
  8. invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
  9. }
  10. }
  • AspectJAfterThrowingAdvice
  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. try {
  3. return mi.proceed();
  4. }
  5. catch (Throwable ex) {
  6. if (shouldInvokeOnThrowing(ex)) {
  7. invokeAdviceMethod(getJoinPointMatch(), null, ex);
  8. }
  9. throw ex;
  10. }
  11. }

这里的调用顺序是怎样的呢?其核心就是通过proceed方法控制流程,每执行完一个Advice就会回到proceed方法中调用下一个Advice。可以思考一下,怎么才能让调用结果满足如下图的执行顺序
在这里插入图片描述
以上就是AOP的链式调用过程,但是这只是只有一个切面类的情况,如果有多个@Aspect类呢,这个调用过程又是怎样的?其核心思想和“栈”一样,就是“先进后出,后进先出”。

在上文创建代理对象的时候有这样一个方法:

  1. protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
  2. //自定义MethodInterceptor.拿到setInterceptorNames方法注入的Interceptor对象
  3. Advisor[] commonInterceptors = resolveInterceptorNames();
  4. List<Object> allInterceptors = new ArrayList<>();
  5. if (specificInterceptors != null) {
  6. allInterceptors.addAll(Arrays.asList(specificInterceptors));
  7. if (commonInterceptors.length > 0) {
  8. if (this.applyCommonInterceptorsFirst) {
  9. allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
  10. }
  11. else {
  12. allInterceptors.addAll(Arrays.asList(commonInterceptors));
  13. }
  14. }
  15. }
  16. Advisor[] advisors = new Advisor[allInterceptors.size()];
  17. for (int i = 0; i < allInterceptors.size(); i++) {
  18. //对自定义的advice要进行包装,把advice包装成advisor对象,切面对象
  19. advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
  20. }
  21. return advisors;
  22. }

这个方法的作用就在于我们可以扩展我们自己的Interceptor,首先通过resolveInterceptorNames方法获取到通过setInterceptorNames方法设置的Interceptor,然后调用DefaultAdvisorAdapterRegistry.wrap方法将其包装为DefaultPointcutAdvisor对象并返回:

  1. public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
  2. if (adviceObject instanceof Advisor) {
  3. return (Advisor) adviceObject;
  4. }
  5. if (!(adviceObject instanceof Advice)) {
  6. throw new UnknownAdviceTypeException(adviceObject);
  7. }
  8. Advice advice = (Advice) adviceObject;
  9. if (advice instanceof MethodInterceptor) {
  10. return new DefaultPointcutAdvisor(advice);
  11. }
  12. for (AdvisorAdapter adapter : this.adapters) {
  13. if (adapter.supportsAdvice(advice)) {
  14. return new DefaultPointcutAdvisor(advice);
  15. }
  16. }
  17. throw new UnknownAdviceTypeException(advice);
  18. }
  19. public DefaultPointcutAdvisor(Advice advice) {
  20. this(Pointcut.TRUE, advice);
  21. }

需要注意DefaultPointcutAdvisor构造器里面传入了一个Pointcut.TRUE,表示这种扩展的Interceptor是全局的拦截器。下面来看看如何使用:

  1. public class MyMethodInterceptor implements MethodInterceptor {
  2. @Override
  3. public Object invoke(MethodInvocation invocation) throws Throwable {
  4. System.out.println("自定义拦截器");
  5. return invocation.proceed();
  6. }
  7. }

首先写一个类实现MethodInterceptor 接口,在invoke方法中实现我们的拦截逻辑,然后通过下面的方式测试,只要UserService 有AOP拦截就会发现自定义的MyMethodInterceptor也生效了。

  1. public void costomInterceptorTest() {
  2. AnnotationAwareAspectJAutoProxyCreator bean = applicationContext.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
  3. bean.setInterceptorNames("myMethodInterceptor ");
  4. UserService userService = applicationContext.getBean(UserService.class);
  5. userService.queryUser("dark");
  6. }

但是如果换个顺序,像下面这样:

  1. public void costomInterceptorTest() {
  2. UserService userService = applicationContext.getBean(UserService.class);
  3. AnnotationAwareAspectJAutoProxyCreator bean = applicationContext.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
  4. bean.setInterceptorNames("myMethodInterceptor ");
  5. userService.queryUser("dark");
  6. }

这时自定义的全局拦截器就没有作用了,这是为什么呢?因为当执行getBean的时候,如果有切面匹配就会通过ProxyFactory去创建代理对象,注意Interceptor是存到这个Factory对象中的,而这个对象和代理对象是一一对应的,因此调用getBean时,还没有myMethodInterceptor这个对象,自定义拦截器就没有效果了,也就是说要想自定义拦截器生效,就必须在代理对象生成之前注册进去。

在上一篇文章我分析了Spring是如何通过三级缓存来解决循环依赖的问题的,但你是否考虑过第三级缓存为什么要存在?我直接将bean存到二级不就行了么,为什么还要存一个ObjectFactory对象到第三级缓存中?这个在学习了AOP之后就很清楚了,因为我们在@Autowired对象时,想要注入的不一定是Bean本身,而是想要注入一个修改过后的对象,如代理对象。在AbstractAutowireCapableBeanFactory.getEarlyBeanReference方法中循环调用了SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference方法,AbstractAutoProxyCreator对象就实现了该方法:

  1. public Object getEarlyBeanReference(Object bean, String beanName) {
  2. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  3. if (!this.earlyProxyReferences.contains(cacheKey)) {
  4. this.earlyProxyReferences.add(cacheKey);
  5. }
  6. // 创建代理对象
  7. return wrapIfNecessary(bean, beanName, cacheKey);
  8. }

因此,当我们想要对循坏依赖的Bean做出修改时,就可以像AOP这样做。

Spring的代理对象基本上都是在Bean实例化完成之后创建的,但在文章开始我就说过,Spring也提供了一个机会在创建Bean对象之前就创建代理对象,在AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation方法中:

  1. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
  2. Object bean = null;
  3. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
  4. // Make sure bean class is actually resolved at this point.
  5. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  6. Class<?> targetType = determineTargetType(beanName, mbd);
  7. if (targetType != null) {
  8. bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
  9. if (bean != null) {
  10. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  11. }
  12. }
  13. }
  14. mbd.beforeInstantiationResolved = (bean != null);
  15. }
  16. return bean;
  17. }
  18. protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
  19. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  20. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  21. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  22. Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
  23. if (result != null) {
  24. return result;
  25. }
  26. }
  27. }
  28. return null;
  29. }

主要是InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法中,这里又会进入到AbstractAutoProxyCreator类中:

  1. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
  2. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
  3. if (targetSource != null) {
  4. if (StringUtils.hasLength(beanName)) {
  5. this.targetSourcedBeans.add(beanName);
  6. }
  7. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  8. Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
  9. this.proxyTypes.put(cacheKey, proxy.getClass());
  10. return proxy;
  11. }
  12. return null;
  13. }
  14. protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
  15. // We can't create fancy target sources for directly registered singletons.
  16. if (this.customTargetSourceCreators != null &&
  17. this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
  18. for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
  19. TargetSource ts = tsc.getTargetSource(beanClass, beanName);
  20. if (ts != null) {
  21. return ts;
  22. }
  23. }
  24. }
  25. // No custom TargetSource found.
  26. return null;
  27. }

看到这里大致应该明白了,先是获取到一个自定义的TargetSource对象,然后创建代理对象,所以我们首先需要自己实现一个TargetSource类,这里直接继承一个抽象类,getTarget方法则返回原始对象:

  1. public class MyTargetSource extends AbstractBeanFactoryBasedTargetSource {
  2. @Override
  3. public Object getTarget() throws Exception {
  4. return getBeanFactory().getBean(getTargetBeanName());
  5. }
  6. }

但这还不够,上面首先判断了customTargetSourceCreators!=null,而这个属性是个数组,可以通过下面这个方法设置进来:

  1. public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
  2. this.customTargetSourceCreators = targetSourceCreators;
  3. }

所以我们还要实现一个TargetSourceCreator类,同样继承一个抽象类实现,并只对userServiceImpl对象进行拦截:

  1. public class MyTargetSourceCreator extends AbstractBeanFactoryBasedTargetSourceCreator {
  2. @Override
  3. protected AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(Class<?> beanClass, String beanName) {
  4. if (getBeanFactory() instanceof ConfigurableListableBeanFactory) {
  5. if(beanName.equalsIgnoreCase("userServiceImpl")) {
  6. return new MyTargetSource();
  7. }
  8. }
  9. return null;
  10. }
  11. }

createBeanFactoryBasedTargetSource方法是在AbstractBeanFactoryBasedTargetSourceCreator.getTargetSource中调用的,而getTargetSource就是在上面getCustomTargetSource中调用的。以上工作做完后,还需要将其设置到AnnotationAwareAspectJAutoProxyCreator对象中,因此需要我们注入这个对象:

  1. @Configuration
  2. public class TargetSourceCreatorBean {
  3. @Autowired
  4. private BeanFactory beanFactory;
  5. @Bean
  6. public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
  7. AnnotationAwareAspectJAutoProxyCreator creator = new AnnotationAwareAspectJAutoProxyCreator();
  8. MyTargetSourceCreator myTargetSourceCreator = new MyTargetSourceCreator();
  9. myTargetSourceCreator.setBeanFactory(beanFactory);
  10. creator.setCustomTargetSourceCreators(myTargetSourceCreator);
  11. return creator;
  12. }
  13. }

这样,当我们通过getBean获取userServiceImpl的对象时,就会优先生成代理对象,然后在调用执行链的过程中再通过TargetSource.getTarget获取到被代理对象。但是,为什么我们在getTarget方法中调用getBean就能拿到被代理对象呢?
继续探究,通过断点我发现从getTarget进入时,在resolveBeforeInstantiation方法中返回的bean就是null了,而getBeanPostProcessors方法返回的Processors中也没有了AnnotationAwareAspectJAutoProxyCreator对象,也就是没有进入到AbstractAutoProxyCreator.postProcessBeforeInstantiation方法中,所以不会再次获取到代理对象,那AnnotationAwareAspectJAutoProxyCreator对象是在什么时候移除的呢?
带着问题,我开始反推,发现在AbstractBeanFactoryBasedTargetSourceCreator类中有这样一个方法buildInternalBeanFactory

  1. protected DefaultListableBeanFactory buildInternalBeanFactory(ConfigurableBeanFactory containingFactory) {
  2. DefaultListableBeanFactory internalBeanFactory = new DefaultListableBeanFactory(containingFactory);
  3. // Required so that all BeanPostProcessors, Scopes, etc become available.
  4. internalBeanFactory.copyConfigurationFrom(containingFactory);
  5. // Filter out BeanPostProcessors that are part of the AOP infrastructure,
  6. // since those are only meant to apply to beans defined in the original factory.
  7. internalBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor ->
  8. beanPostProcessor instanceof AopInfrastructureBean);
  9. return internalBeanFactory;
  10. }

在这里移除掉了所有AopInfrastructureBean的子类,而AnnotationAwareAspectJAutoProxyCreator就是其子类,那这个方法是在哪里调用的呢?继续反推:

  1. protected DefaultListableBeanFactory getInternalBeanFactoryForBean(String beanName) {
  2. synchronized (this.internalBeanFactories) {
  3. DefaultListableBeanFactory internalBeanFactory = this.internalBeanFactories.get(beanName);
  4. if (internalBeanFactory == null) {
  5. internalBeanFactory = buildInternalBeanFactory(this.beanFactory);
  6. this.internalBeanFactories.put(beanName, internalBeanFactory);
  7. }
  8. return internalBeanFactory;
  9. }
  10. }
  11. public final TargetSource getTargetSource(Class<?> beanClass, String beanName) {
  12. AbstractBeanFactoryBasedTargetSource targetSource =
  13. createBeanFactoryBasedTargetSource(beanClass, beanName);
  14. // 创建完targetSource后就移除掉AopInfrastructureBean类型的BeanPostProcessor对象,如AnnotationAwareAspectJAutoProxyCreator
  15. DefaultListableBeanFactory internalBeanFactory = getInternalBeanFactoryForBean(beanName);
  16. ......
  17. return targetSource;
  18. }

至此,关于TargetSource接口扩展的原理就搞明白了。

本篇篇幅比较长,主要搞明白Spring代理对象是如何创建的以及AOP链式调用过程,而后面的扩展则是对AOP以及Bean创建过程中一些疑惑的补充,可根据实际情况学习掌握。

版权声明:本文为yewy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/yewy/p/13199260.html