关于java:AOP源码解析之二创建AOP代理前传获取AOP信息

31次阅读

共计 15060 个字符,预计需要花费 38 分钟才能阅读完成。

AOP 源码解析之二 - 创立 AOP 代理前传,获取 AOP 信息。

上篇文章对 AOP 的基本概念说分明了,那么接下来的 AOP 还剩下两个大的步骤获取定义的 AOP 信息,生成代理对象扔到 beanFactory 中。

本篇文章重点对前半部分,如何获取到 AOP 信息的过程解读。

在 Spring 的外围办法 Refresh 办法中,aop 是在

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

开始切入的,该文章就开始深刻这个办法进行解析。

@Nullable
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        // 检测是否被解析过
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            // hasInstantiationAwareBeanPostProcessors() 是来判断容器中是否有 InstantiationAwareBeanPostProcessor 的实现 bean
            // AOP 切面后置处理器 AspectJAwareAdvisorAutoProxyCreator 就实现了 InstantiationAwareBeanPostProcessor 接口
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    // 执行实现了 InstantiationAwareBeanPostProcessor 接口的 BeanPostProcessor 中的前置解决办法 postProcessBeforeInstantiation 办法
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        // 执行实现了 InstantiationAwareBeanPostProcessor 接口的 BeanPostProcessor 中的后置解决办法 postProcessAfterInitialization 办法
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

见名知意,resolveBeforeInstantiation(执行初始化前办法),这一步次要判断一下工厂中是否有 InstantiationAwareBeanPostProcessor 的实现 bean。InstantiationAwareBeanPostProcessor 应该是 AOP 最外围的接口了。

咱们看一下 InstantiationAwareBeanPostProcessor 的继承构造。

咱们具体的说下 InstantiationAwareBeanPostProcessor 这个接口。

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

   boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

   PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}

它和 BeanPostProcessor 的办法十分类似,而且它还继承了 BeanPostProcessor。

上面是 BeanPostProcessor 中的两个办法:

Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

发现没有,InstantiationAwareBeanPostProcessor 是 Instantiation,BeanPostProcessor 是 Initialization,它代表的是 bean 在实例化实现并且属性注入实现,在执行 init-method 的前后进行作用的。

而 InstantiationAwareBeanPostProcessor 的执行机会要后面一些,咱们回到 refresh 办法的 doCreateBean 中看一下。

看到这读者想必对于 aop 的执行机会曾经隐隐约约的心里有个大略了。

咱们定义的盘绕告诉,创立代理肯定是在 postProcessBeforeInitialization 实现的。

咱们的重点就是看看 postProcessBeforeInitialization 的办法中的告诉怎么获取,怎么创立代理对象的进行具体的解读。

本文先对前半部分解读。

咱们持续看 postProcessBeforeInitialization 有哪些实现类。

咱们重点看 AbstractAutoProxyCreator 的实现类。

@Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // 1. 判断以后 bean 是否须要被代理,如果须要则进行封装
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //1. 判断以后 bean 是否须要被代理,如果须要则进行封装
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

如果须要代理执行继 wrapIfNecessary 办法。

// 这个办法将返回代理类
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 1. 判断以后 bean 是否在 targetSourcedBeans 缓存中存在(曾经解决过),如果存在,则间接返回以后 bean
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}
        // 2. 在 advisedBeans 缓存中存在,并且 value 为 false,则代表无需解决
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}
        // 3.bean 的类是 aop 基础设施类 || bean 应该跳过,则标记为无需解决,并返回
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        // 4. 获取以后 bean 的 Advices 和 Advisors
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        // 5. 如果存在增强器则创立代理
        if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 创立代理... 创立代理... 创立代理...
            // 5.1 创立代理对象:这边 SingletonTargetSource 的 target 属性寄存的就是咱们原来的 bean 实例(也就是被代理对象),// 用于最初减少逻辑执行结束后,通过反射执行咱们真正的办法时应用(method.invoke(bean, args))Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            // 5.2 创立完代理后,将 cacheKey -> 代理类的 class 放到缓存
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
        // 6. 标记为无需解决
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

4.1 咱们先查看第一条主线,获取以后 bean 的 Advices 和 Advisors

@Override
    @Nullable
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

        // 1. 找到符合条件的 Advisor
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            // 2. 如果没有符合条件的 Advisor,则返回 null
            return DO_NOT_PROXY;
        }
        return advisors.toArray();}

注:Advisors 即是 aop 的盘绕告诉。

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // 1. 查找所有的候选 Advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 2. 从所有候选的 Advisor 中找出符合条件的
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        // 3. 扩大办法,留个子类实现
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            // 4. 对符合条件的 Advisor 进行排序
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

这一步所做的事很简略,就是查找所有候选的 Advisor,然而调用链路特地的长,如果将这些彻底搞明确,还是须要消耗一番功夫的,读者能够抉择深刻水平。

1、寻找可用的 Advisor

public List<Advisor> findAdvisorBeans() {
        // Determine list of advisor bean names, if not cached already.
        // 1. 确认 advisor 的 beanName 列表,优先从缓存中拿
        String[] advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the auto-proxy creator apply to them!
            //  1.1 如果缓存为空,则获取 class 类型为 Advisor 的所有 bean 名称
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
            this.cachedAdvisorBeanNames = advisorNames;
        }
        if (advisorNames.length == 0) {return new ArrayList<>();
        }

        // 2. 遍历解决 advisorNames
        List<Advisor> advisors = new ArrayList<>();
        for (String name : advisorNames) {if (isEligibleBean(name)) {
                // 2.1 跳过以后正在创立的 advisor
                if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isTraceEnabled()) {logger.trace("Skipping currently created advisor'" + name + "'");
                    }
                }
                else {
                    try {
                        // 2.2 通过 beanName 获取对应的 bean 对象,并增加到 advisors
                        advisors.add(this.beanFactory.getBean(name, Advisor.class));
                    }
                    catch (BeanCreationException ex) {Throwable rootCause = ex.getMostSpecificCause();
                        if (rootCause instanceof BeanCurrentlyInCreationException) {BeanCreationException bce = (BeanCreationException) rootCause;
                            String bceBeanName = bce.getBeanName();
                            if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {if (logger.isTraceEnabled()) {
                                    logger.trace("Skipping advisor'" + name +
                                            "'with dependency on currently created bean:" + ex.getMessage());
                                }
                                // Ignore: indicates a reference back to the bean we're trying to advise.
                                // We want to find advisors other than the currently created bean itself.
                                continue;
                            }
                        }
                        throw ex;
                    }
                }
            }
        }
        // 3. 返回符合条件的 advisor 列表
        return advisors;
    }
/**
 * 找到符合条件的 Advisor
 * @return
 */
@Override
protected List<Advisor> findCandidateAdvisors() {
   // Add all the Spring advisors found according to superclass rules.
   List<Advisor> advisors = super.findCandidateAdvisors();
   // Build Advisors for all AspectJ aspects in the bean factory.
   if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   }
   return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
   List<String> aspectNames = this.aspectBeanNames;

   // 1. 如果 aspectNames 为空,则进行解析
   if (aspectNames == null) {synchronized (this) {
         aspectNames = this.aspectBeanNames;
         if (aspectNames == null) {List<Advisor> advisors = new ArrayList<>();
            aspectNames = new ArrayList<>();
            // 1.1 获取所有的 beanName
            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
            // 1.2 循环遍历所有的 beanName,找出对应的加强办法
            for (String beanName : beanNames) {
               // 1.3 不非法的 beanName 则跳过,默认返回 true,子类能够笼罩实现,AnnotationAwareAspectJAutoProxyCreator
               // 实现了本人的逻辑,反对应用 includePatterns 进行筛选
               if (!isEligibleBean(beanName)) {continue;}
               // We must be careful not to instantiate beans eagerly as in this case they
               // would be cached by the Spring container but would not have been weaved.
               // 获取 beanName 对应的 bean 的类型
               Class<?> beanType = this.beanFactory.getType(beanName);
               if (beanType == null) {continue;}
               // 1.4 如果 beanType 存在 Aspect 注解则进行解决
               if (this.advisorFactory.isAspect(beanType)) {
                  // 将存在 Aspect 注解的 beanName 增加到 aspectNames 列表
                  aspectNames.add(beanName);
                  // 新建切面元数据
                  AspectMetadata amd = new AspectMetadata(beanType, beanName);
                  if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                     // 应用 BeanFactory 和 beanName 创立一个 BeanFactoryAspectInstanceFactory,次要用来创立切面对象实例
                     MetadataAwareAspectInstanceFactory factory =
                           new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                     // 1.5 解析标记 AspectJ 注解中的加强办法 *********************
                     List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                     // 1.6 放到缓存中
                     if (this.beanFactory.isSingleton(beanName)) {
                        // 如果 beanName 是单例则间接将解析的加强办法放到缓存
                        this.advisorsCache.put(beanName, classAdvisors);
                     }
                     else {
                        // 如果不是单例,则将 factory 放到缓存,之后能够通过 factory 来解析加强办法
                        this.aspectFactoryCache.put(beanName, factory);
                     }
                     // 1.7 将解析的增强器增加到 advisors
                     advisors.addAll(classAdvisors);
                  }
                  else {
                     // Per target or per this.
                     if (this.beanFactory.isSingleton(beanName)) {
                        // 名称为 beanName 的 Bean 是单例,但切面实例化模型不是单例,则抛异样
                        throw new IllegalArgumentException("Bean with name'" + beanName +
                              "'is a singleton, but aspect instantiation model is not singleton");
                     }
                     MetadataAwareAspectInstanceFactory factory =
                           new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                     // 将 factory 放到缓存,之后能够通过 factory 来解析加强办法
                     this.aspectFactoryCache.put(beanName, factory);
                     // 解析标记 AspectJ 注解中的加强办法,并增加到 advisors 中
                     advisors.addAll(this.advisorFactory.getAdvisors(factory));
                  }
               }
            }
            // 1.9 将解析进去的切面 beanName 放到缓存 aspectBeanNames
            this.aspectBeanNames = aspectNames;
            return advisors;
         }
      }
   }

   if (aspectNames.isEmpty()) {return Collections.emptyList();
   }
   List<Advisor> advisors = new ArrayList<>();
   for (String aspectName : aspectNames) {List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
      if (cachedAdvisors != null) {advisors.addAll(cachedAdvisors);
      }
      else {MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
         advisors.addAll(this.advisorFactory.getAdvisors(factory));
      }
   }
   // 1.10 最初返回解析进去的增强器
   return advisors;
}
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
   // 1. 后面咱们将 beanClass 和 beanName 封装成了 aspectInstanceFactory 的 AspectMetadata 属性,// 这边能够通过 AspectMetadata 属性从新获取到以后解决的切面类
   Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
   // 2. 获取以后解决的切面类的名字
   String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
   // 3. 校验切面类
   validate(aspectClass);

   // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
   // so that it will only instantiate once.
   // 4. 应用装璜器包装 MetadataAwareAspectInstanceFactory,以便它只实例化一次。MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
         new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

   List<Advisor> advisors = new ArrayList<>();
   // 5. 获取切面类中的办法(也就是咱们用来进行逻辑加强的办法,被 @Around、@After 等注解润饰的办法,应用 @Pointcut 的办法不解决)for (Method method : getAdvisorMethods(aspectClass)) {
      // 6. 解决 method,获取增强器
      Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
      if (advisor != null) {
         // 7. 如果增强器不为空,则增加到 advisors
         advisors.add(advisor);
      }
   }

   // If it's a per target aspect, emit the dummy instantiating aspect.
   if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
      // 8. 如果寻找的增强器不为空而且又配置了加强提早初始化,那么须要在首位退出同步实例化增强器(用以保障加强应用之前的实例化)Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
      advisors.add(0, instantiationAdvisor);
   }

   // Find introduction fields.
   // 9. 获取 DeclareParents 注解
   for (Field field : aspectClass.getDeclaredFields()) {Advisor advisor = getDeclareParentsAdvisor(field);
      if (advisor != null) {advisors.add(advisor);
      }
   }

   return advisors;
}
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
      int declarationOrderInAspect, String aspectName) {

   // 1. 校验切面类
   validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

   // 2.AspectJ 切点信息的获取(例如:表达式),就是指定注解的表达式信息的获取,// 如:@Around("execution(* com.joonwhee.open.aop.*.*(..))")
   AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
   // 3. 如果 expressionPointcut 为 null,则间接返回 null
   if (expressionPointcut == null) {return null;}

   // 4. 依据切点信息生成增强器
   return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

获取到 @Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut 定义注解信息

@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
   // 1. 查找并返回给定办法的第一个 AspectJ 注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)// 因为咱们之前把 @Pointcut 注解的办法跳过了,所以这边必然不会获取到 @Pointcut 注解
   AspectJAnnotation<?> aspectJAnnotation =
         AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
   // 2. 如果办法没有应用 AspectJ 的注解,则返回 null
   if (aspectJAnnotation == null) {return null;}

   // 3. 应用 AspectJExpressionPointcut 实例封装获取的信息
   AspectJExpressionPointcut ajexp =
         new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
   // 提取失去的注解中的表达式,// 例如:@Around("execution(* com.joonwhee.open.aop.*.*(..))"),失去:execution(* com.joonwhee.open.aop.*.*(..))
   ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
   if (this.beanFactory != null) {ajexp.setBeanFactory(this.beanFactory);
   }
   return ajexp;
}
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
   // 设置要查找的注解类
   for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
      // 查找办法上是否存在以后遍历的注解,如果有则返回
      AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
      if (foundAnnotation != null) {return foundAnnotation;}
   }
   return null;
}

2、获取切点当前就须要生成增强器了。

 new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName)
/**
 * 依据切点信息生成增强器
 * @param declaredPointcut
 * @param aspectJAdviceMethod
 * @param aspectJAdvisorFactory
 * @param aspectInstanceFactory
 * @param declarationOrder
 * @param aspectName
 */
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
      Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
      MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

   // 1. 简略的将信息封装在类的实例中
   this.declaredPointcut = declaredPointcut;
   this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
   this.methodName = aspectJAdviceMethod.getName();
   this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
   // aspectJAdviceMethod 保留的是咱们用来进行逻辑加强的办法(@Around、@After 等润饰的办法)this.aspectJAdviceMethod = aspectJAdviceMethod;
   this.aspectJAdvisorFactory = aspectJAdvisorFactory;
   this.aspectInstanceFactory = aspectInstanceFactory;
   this.declarationOrder = declarationOrder;
   this.aspectName = aspectName;

   // 2. 是否须要提早实例化
   if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
      // Static part of the pointcut is a lazy type.
      Pointcut preInstantiationPointcut = Pointcuts.union(aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

      // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
      // If it's not a dynamic pointcut, it may be optimized out
      // by the Spring AOP infrastructure after the first evaluation.
      this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
      this.lazy = true;
   }
   else {
      // A singleton aspect.
      this.pointcut = this.declaredPointcut;
      this.lazy = false;
      // 3. 实例化增强器:依据注解中的信息初始化对应的增强器
      this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
   }
}

通过以上长长的源码剖析过程,就将 aop 的第一个大过程,获取到咱们定义的 @Before、@After 的办法当前,进行加强,下一步就要拿到这些获取的信息去创立代理对象了。

正文完
 0