zoukankan      html  css  js  c++  java
  • AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍

    AspectJAwareAdvisorAutoProxyCreator 的类图

    上图中一些 类/接口 的介绍:

    AspectJAwareAdvisorAutoProxyCreator : 公开了AspectJ的调用上下文,并弄清楚来自同一切面的多个Advisor在AspectJ中的优先级规则。

    AbstractAdvisorAutoProxyCreator : 通用自动代理创建器,它基于检测到的每个顾问程序为特定bean构建AOP代理。

    AbstractAutoProxyCreator扩展了 ProxyProcessorSupport,实现了SmartInstantiationAwareBeanPostProcessor、BeanFactoryAware 接口,是BeanPostProcessor 实现,该实现使用AOP代理包装每个合格的bean,并在调用bean本身之前委派给指定的拦截器。

    BeanFactoryAware : 实现了该接口的Bean可以知道它属于那个 BeanFactory,Bean可以通过Spring容器查找它的协同者(依赖查找),但大多数的Bean是通过构造器参数和Bean方法(依赖注入)来获取它的协同者。

    BeanPostProcessor :工厂钩子,允许自定义修改新的bean实例。例如,检查标记接口或使用代理包装bean。如果我们需要在Spring容器中完成Bean的实例化,配置和其初始化前后添加一些自己的逻辑处理,我们就可以定义一个或多个BeanPostProcessor接口的实现,然后注册到容器中。

    InstantiationAwareBeanPostProcessor :  BeanPostProcessor 的子接口,它添加了实例化之前的回调,以及实例化之后但设置了显式属性或自动装配之前的回调。它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor 接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置。

    SmartInstantiationAwareBeanPostProcessorInstantiationAwareBeanPostProcessor 接口的扩展,多出了3个方法,添加了用于预测已处理bean的最终类型的回调,再加上父接口的5个方法,所以实现这个接口需要实现8个方法,主要作用也是在于目标对象的实例化过程中需要处理的事情。

    AspectJAwareAdvisorAutoProxyCreator为 AspectJ 切面类创建自动代理。

      BeanPostProcessor 接口中的两个方法 postProcessBeforeInitialization 和 postProcessAfterInitialization,作用是对Bean初始化前后添加一些自己的逻辑。

    1     @Nullable
    2     default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    3         return bean;
    4     }
    5 
    6     @Nullable
    7     default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    8         return bean;
    9     }

      InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,它额外增加了3个新的方法:postProcessBeforeInstantiation( 目标对象被实例化之前调用的方法,可以返回目标实例的一个代理用来代替目标实例 )、postProcessAfterInstantiation(该方法在Bean实例化之后执行,返回false,会忽略属性值的设置;如果返回true,会按照正常流程设置属性值) 和 postProcessPropertyValues(对属性值进行修改,未来版本将会删除)。

     1     @Nullable
     2     default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
     3         return null;
     4     }
     5 
     6     default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
     7         return true;
     8     }
     9 
    10     @Nullable
    11     default PropertyValues postProcessPropertyValues(
    12             PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    13 
    14         return pvs;
    15     }

      SmartInstantiationAwareBeanPostProcessor接口继承InstantiationAwareBeanPostProcessor接口,里面定义了3个方法:predictBeanType(预测Bean的类型)、determineCandidateConstructors(选择合适的构造器)、getEarlyBeanReference(解决循环引用问题)。

     1     @Nullable
     2     default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
     3         return null;
     4     }
     5 
     6     @Nullable
     7     default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
     8         return null;
     9     }
    10 
    11     default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
    12         return bean;
    13     }

      AbstractAutoProxyCreator 是AOP的一个核心类,它实现了SmartInstantiationAwareBeanPostProcessor、BeanFactoryAware 接口,实现了代理创建的逻辑,使用AOP代理包装每个合格的bean,并在调用bean本身之前委派给指定的拦截器。

      AbstractAdvisorAutoProxyCreator 通用自动代理创建器,它基于检测每个bean的增强器,为特殊的bean构建AOP代理。子类可以重写此findCandidateAdvisors()方法,以返回适用于任何对象的advisor的自定义列表,子类还可以重写继承的AbstractAutoProxyCreator.shouldSkip()方法,以将某些对象排除在自动代理之外。

    1     protected List<Advisor> findCandidateAdvisors() {
    2         Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    3         return this.advisorRetrievalHelper.findAdvisorBeans();
    4     }

      AspectJAwareAdvisorAutoProxyCreator 扩展 AbstractAdvisorAutoProxyCreator,公开了AspectJ的调用上下文,并在多个增强器来自同一切面时搞清楚AspectJ的建议优先级顺序。按AspectJ优先级排序其余部分:

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

      在增强链头部增加一个ExposeInvocationInterceptor,使用AspectJ表达式切入点和使用AspectJ样式的advisor时,需要这些附加advisor。

    1     protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    2         AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
    3     }

      如果此后处理器不应该考虑将给定的bean用于自动代理,子类应重写此方法以返回true

     1     @Override
     2     protected boolean shouldSkip(Class<?> beanClass, String beanName) {
     3         // TODO: Consider optimization by caching the list of the aspect names
     4         List<Advisor> candidateAdvisors = findCandidateAdvisors();
     5         for (Advisor advisor : candidateAdvisors) {
     6             if (advisor instanceof AspectJPointcutAdvisor &&
     7                     ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
     8                 return true;
     9             }
    10         }
    11         return super.shouldSkip(beanClass, beanName);
    12     }

      AspectJAwareAdvisorAutoProxyCreator 还有一个子类叫 AnnotationAwareAspectJAutoProxyCreator,子类AnnotationAwareAspectJAutoProxyCreator是用于处理当前应用程序上下文中的所有AspectJ注释方面以及Spring Advisor。如果Spring AOP的基于代理的模型能够应用任何AspectJ注释的类,它们的advisor将被自动识别,这涵盖了方法执行连接点,Spring Advisor的处理遵循AbstractAdvisorAutoProxyCreator中建立的规则。

    生成代理对象

      从使用<aop:xxx>标签来自动生成代理的话,先看看AopNamespaceHandler,使用<aop:config>标签则使用 ConfigBeanDefinitionParser 解析,使用了<aop:aspectj-autoproxy>标签则使用 AspectJAutoProxyBeanDefinitionParser 解析,依次类推。

     1     @Override
     2     public void init() {
     3         // In 2.0 XSD as well as in 2.1 XSD.
     4         registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
     5         registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
     6         registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
     7 
     8         // Only in 2.0 XSD: moved to context namespace as of 2.1
     9         registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    10     }
    • <aop:config>方式使用 AspectJAwareAdvisorAutoProxyCreator 创建代理

    • <aop:aspectj-autoproxy>使用 AnnotationAwareAspectJAutoProxyCreator 创建代理

    ConfigBeanDefinitionParser.java

     1     @Override
     2     @Nullable
     3     public BeanDefinition parse(Element element, ParserContext parserContext) {
     4         CompositeComponentDefinition compositeDef =
     5                 new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
     6         parserContext.pushContainingComponent(compositeDef);
     7 
     8         configureAutoProxyCreator(parserContext, element); // 注册AspectJAwareAdvisorAutoProxyCreator
     9 
    10         List<Element> childElts = DomUtils.getChildElements(element);
    11         for (Element elt: childElts) {
    12             String localName = parserContext.getDelegate().getLocalName(elt);
    13             if (POINTCUT.equals(localName)) {
    14                 parsePointcut(elt, parserContext);
    15             }
    16             else if (ADVISOR.equals(localName)) {
    17                 parseAdvisor(elt, parserContext);
    18             }
    19             else if (ASPECT.equals(localName)) {
    20                 parseAspect(elt, parserContext);
    21             }
    22         }
    23 
    24         parserContext.popAndRegisterContainingComponent();
    25         return null;
    26     }
    27 
    28     private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
    29         AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
    30     }

    AopConfigUtils.java

    1     public static void registerAspectJAutoProxyCreatorIfNecessary(
    2             ParserContext parserContext, Element sourceElement) {
    3        // 在这里注册的是AspectJAwareAdvisorAutoProxyCreator
    4         BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
    5                 parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    6         useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    7         registerComponentIfNecessary(beanDefinition, parserContext); // 注册组件
    8     }
    1     @Nullable
    2     public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
    3             BeanDefinitionRegistry registry, @Nullable Object source) {
    4 
    5         return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
    6     }

      AspectJAwareAdvisorAutoProxyCreator 实现了 BeanPostProcessor 等上面介绍的接口,主要作用于Bean初始化前后,实例化前后,所有的Bean都被作用到。InstantiationAwareBeanPostProcessor 是 BeanPostProcessor的子接口,但它的调用时间点发生在Bean实例化前,在真正调用doCreateBean()创建bean实例之前执行postProcessBeforeInstantiation()。

    AbstractAutoProxyCreator.java

     1     @Override
     2     public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
     3         Object cacheKey = getCacheKey(beanClass, beanName);  // 得到一个缓存的唯一key(根据beanClass和beanName生成唯一key)
     4      // 如果当前targetSourcedBeans(通过自定义TargetSourceCreator创建的TargetSource)不包含cacheKey
     5         if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
     6             if (this.advisedBeans.containsKey(cacheKey)) {  //advisedBeans(已经被增强的Bean,即AOP代理对象)中包含当前cacheKey,返回null,即走Spring默认流程
     7                 return null;
     8             }
     9             if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {// 如果是基础设施类(如Advisor、Advice、AopInfrastructureBean的实现)不进行处理;(略)
    10                 this.advisedBeans.put(cacheKey, Boolean.FALSE);
    11                 return null;
    12             }
    13         }
    14 
    15         // 如果有自定义的TargetSource,在此处创建代理
    16         // 禁止目标Bean的不必要的默认实例化:
    17         // TargetSource将以自定义方式处理目标实例。
    18         TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    19         if (targetSource != null) {
    20             if (StringUtils.hasLength(beanName)) {
    21                 this.targetSourcedBeans.add(beanName);
    22             }
    23             Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
    24             Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
    25             this.proxyTypes.put(cacheKey, proxy.getClass());
    26             return proxy;
    27         }
    28 
    29         return null;
    30     }

    通过 AbstractAutoProxyCreator 中的 postProcessAfterInitialization() 创建AOP代理。

     1     @Override
     2     public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
     3         if (bean != null) {
     4             Object cacheKey = getCacheKey(bean.getClass(), beanName);
     5             if (!this.earlyProxyReferences.contains(cacheKey)) {  // 如果之前调用过getEarlyBeanReference获取包装目标对象到AOP代理对象(如果需要),则不再执行
     6                 return wrapIfNecessary(bean, beanName, cacheKey);  // 包装目标对象到AOP代理对象(如果需要)
     7             }
     8         }
     9         return bean;
    10     }
    11     
    12     protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    13         if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { // 通过TargetSourceCreator进行自定义TargetSource不需要包装
    14             return bean;
    15         }
    16         if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {  // 不应该被增强对象不需要包装
    17             return bean;
    18         }
    19         if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { // 基础设施或应该skip的不需要保证
    20             this.advisedBeans.put(cacheKey, Boolean.FALSE);
    21             return bean;
    22         }
    23 
    24         // 如果有advise则创建代理。
    25         Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    26         if (specificInterceptors != DO_NOT_PROXY) {
    27             this.advisedBeans.put(cacheKey, Boolean.TRUE);
    28             Object proxy = createProxy(
    29                     bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // 创建代理对象
    30             this.proxyTypes.put(cacheKey, proxy.getClass());
    31             return proxy;
    32         }
    33 
    34         this.advisedBeans.put(cacheKey, Boolean.FALSE);
    35         return bean;
    36     }

    参考:

    Spring内部的BeanPostProcessor接口总结

    【Spring源码分析】AOP源码解析(下篇)

  • 相关阅读:
    error while loading shared libraries: libhwloc.so.5: cannot open shared object file: No such file or directory
    Mac刷新DNS,修改/etc/hosts立即生效
    zxing生成识别二维码
    电脑M2接口不是磁盘0问题
    WSL
    Ubuntu安装Docker
    Win10关闭自动更新和防护
    Mysql的5种日志
    开发常用工具Windows
    log4j2高危漏洞
  • 原文地址:https://www.cnblogs.com/magic-sea/p/11707060.html
Copyright © 2011-2022 走看看