25.AOP的第二个时机之BeanPostProcessor后置处理

331 阅读8分钟

AOP的原理可以简单这么认为,代理对象持有被代理对象(因为代理对象的字段并不会被赋值,都是null,所以需要用到被代理对象字段的值),通过在调用被代理对象方法前后做一些事情。

在Spring中,我们经常会为我们的Bean做AOP,根据上面我们知道,代理对象需要引用被代理对象,那就需要在Bean初始化完成之后再对Bean做代理。因为Bean初始化完成之后就是一个可用的Bean了,而且会被放入IOC容器,我们需要在这个Bean被放入IOC容器之前生成它的代理对象,并代替原先的类放入IOC容器中。

参考链接:blog.csdn.net/qq_41084438…

image.png

这是一个Bean的生命周期流程,当它执行完第六步,也就是初始化方法执行完毕之后,这个Bean就可用了。而第七步是Spring给我们提供的扩展点,在这一步可以拿到可用的原始对象,我们的代理对象生成和替换就是在这里。

public interface BeanPostProcessor {

    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    	return bean;
    }


    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    	return bean;
    }

}

doGetBean

在循环依赖中我们讲了spring实例化bean的入口,refresh->finishBeanFactoryInitialization->preInstantiateSingletons->getBean->doGetBean,看doGetBean中的如下代码

if (mbd.isSingleton()) {
    // 实例化bean
    sharedInstance = getSingleton(beanName, () -> {
        try {
            // 真正的完成bean的创建
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance
                    (sharedInstance, name, beanName, mbd);
}

createBean

createBean(beanName, mbd, args);方法真正的完成了bean的实例化,包括循环依赖、AOP、生命周期等。

所谓的AOP无非就是将bean加强,在bean的方法前后加上其他的方法而已,bean的class在虚拟机启动的时候就加载到JVM里了,我们不会通过修改class来动态扩展bean的功能,但是可以新生成一个类(动态代理类),这个类呢,包含了bean的所有功能,同时又进行了加强,然后将这个动态代理类实例化,替换掉原有的bean,最后放到spring单例池中。

如果你的类没有被其他类依赖,那么可以在doCreateBean之前就创建好代理对象。

//给Bean后置处理器一个机会,返回一个替代目标对象的代理对象。
//就在这里
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
    //注意如果有 InstantiationAwareBeanPostProcessor类型的接口
    //并返回了自定义对象 这里会直接返回
    return bean;
}
//如果上面直接返回了bean 下面的doCreateBean就不会执行
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
// 给Bean后置处理器一个机会,返回一个替代目标对象的代理对象。
@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.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    //调用InstantiationAwareBeanPostProcessor的 
                    //postProcessBeforeInstantiation
                    //参数是Class
                    bean = applyBeanPostProcessorsBeforeInstantiation
                                                        (targetType, beanName);
                    //这里返回的是null
                    if (bean != null) {
                        //调用BeanPostProcessor的 postProcessAfterInitialization
                        //注意是BeanPostProcessor
                        bean = applyBeanPostProcessorsAfterInitialization
                                                                (bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

上篇文章提到如果applyBeanPostProcessorsBeforeInstantiation方法返回bean不为空,则实例化结束。不执行下面的doCreateBean方法。

本篇文章和上篇文章相反本篇文章要执行doCreateBean方法。

看下org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      /***
       * 创建bean实例 仅仅是创建bean实例
       * 1.判断是否存在Supplier和Factory-Method如果有那么就使用并创建实例
       *  否则就选择使用构造函数进行构造
       * 2.计算构造函数至少有几个参数 选择构造函数
       * 3.选择构造函数的参数 下标&通用
       * 4.计算构造函数的参数权重
       * instanceWrapper实现了 ConfigurablePropertyAccessor
       * 是一个包装类 该类的属性可以编辑
       * instanceWrapper有一个属性WrappedInstance 里面放的就是我们构造的实例
       */
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }
 
   //允许  post-processors 修改 beanDefinition
   //这里都已经构造完了实例 在修改beanDefinition 有什么意义呢?
   //意义在于虽然构造完了 还没初始化完呀 它的属性这些东西还没设置值
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            //调用 MergedBeanDefinitionPostProcessor
            //查找出满足条件的属性、方法, 将他们封装起来, 以便后面在填充属性的时候可以直接使用
            //https://juejin.cn/post/6844904167945797640
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }
 
   /***
    * 是否需要提前暴露
    * 判断条件:
    * 1.是单例
    * 2.允许循环依赖
    * 3.bean正在被创建
    */
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   //需要提前暴露
   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      /***
       * singletonObjects 一级缓存池
       * earlySingletonObjects 二级缓存池
       * singletonFactories 三级缓存池
       * 将ObjectFactory<?> singletonFactory 加入三级缓存 singletonFactories
       */
      addSingletonFactory(
            beanName,
            //getEarlyBeanReference放入了提前实例化但是未初始化的对象
            //getEarlyBeanReference中获取了所有的SmartInstantiationAwareBeanPostProcessor并调用
            //SmartInstantiationAwareBeanPostProcessor中getEarlyBeanReference是一个默认方法
            //默认返回的是传入的bean
            () -> getEarlyBeanReference(beanName, mbd, bean)
      );
   }

   // Initialize the bean instance.
   //这个bean已经放入了 getEarlyBeanReference(beanName, mbd, bean)
   Object exposedObject = bean;
   try {
      /***
       * 1.属性填充
       * 2.处理属性依赖
       * 传入的是 BeanWrapper
       */
      populateBean(beanName, mbd, instanceWrapper);
      /***
       * 初始化bean
       * 如果bean实现了以下接口
       * BeanNameAware, BeanFactoryAware, ApplicationContextAware
       * 则调用对应接口的方法
       * 最后bean的代理对象就是在这里被创建的
       */
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException 
              && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }
   /***
    * 是否需要提前暴露 earlySingletonExposure = true
    * 判断条件:
    * 1.是单例
    * 2.允许循环依赖
    * 3.bean正在被创建
    */
   if (earlySingletonExposure) {
      // A 和 B 循环依赖
      // 对于A来说
      // 如果没有循环依赖不会从三级缓存获取 这里直接返回空
      // 如果没有循环依赖 返回空 因为allowEarlyReference是false 所以不会不到三级缓存拿
      // 如果有循环依赖 在B填充属性A对象时 会在填充属性的方法中调用 getSingleton(beanName, true);
      // 因为allowEarlyReference是true 所以会到三级缓存拿 并放入二级缓存
      // 然后在这里获取的就是二级缓存中的对象

      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         //判断代理的对象和提前暴露的对象是不是还是一个 注意使用的是 ==
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         //如果不是一个判断是否有依赖该bean的对象
         }else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            //如果有抛出异常
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean as disposable.
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

populateBean完成了bean的实例化及循环依赖,继续看initializeBean方法,这个方法就是开启了声明周期,AOP实现也是在这里面。

在docreateBean中执行了exposedObject = initializeBean(beanName, exposedObject, mbd);

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);这个方法就是完成了AOP代理的实现,他是怎么实现的呢???

在initializeBean方法中有2个重要的方法,分别是执行BeanPostProcessor的前置方法和后置方法。

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

分别对应 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

等等这个applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)方法 不是在上一篇文章就执行过吗?

非也非也。

上一篇文章中执行的是applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)

注意看第一个参数,分别是Class 和 Object 。

哦,上一篇文章中对象还没产生,执行的是applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) 所以需要参数需要传1个Class。

这一篇文章bean已经被实例化创建出来了,所以直接传入的是1个被实例化创建出来的bean。

ok,假装很有道理接着往下看

先看AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessBeforeInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}

getBeanPostProcessors()返回值如下:

result = {CopyOnWriteArrayList@1674}  size = 7
 0 = {ApplicationContextAwareProcessor@1076} 
 1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1337} 
 2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@1355} 
 3 = {AnnotationAwareAspectJAutoProxyCreator@1492} "proxyTargetClass=false; optimize=false; opaque=false; exposeProxy=false; frozen=false"
 4 = {CommonAnnotationBeanPostProcessor@1362} 
 5 = {AutowiredAnnotationBeanPostProcessor@1354} 
 6 = {ApplicationListenerDetector@1676} 

其中有1个AnnotationAwareAspectJAutoProxyCreator,看下postProcessBeforeInitialization的逻辑。

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
       return bean;
    }

原来postProcessBeforeInitialization啥也不做呀。

**注意下面获取的是BeanPostProcessor,还是AnnotationAwareAspectJAutoProxyCreator。**看下AbstractAutoProxyCreator#postProcessAfterInitialization

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
          //在这里创建代理
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

此时AOP创建代理的第二个时机出现了,就在AbstractAutoProxyCreator#postProcessAfterInitialization。

进入wrapIfNecessary方法。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && 
            this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
        //isInfrastructureClass(beanClass)
        //判断我们这个业务类是否需要被代理,进入isInfrastructureClass代码
        //判断Advice、Pointcut、Advisor是否是beanClass的超类或者超接口
        //shouldSkip(beanClass, beanName)
        //主要是判断beanName不为空且不是original instance
        //2个条件都是false 说明需要代理
    if (isInfrastructureClass(bean.getClass())
                || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
​
    // Create proxy if we have advice.
    // 获取通知
    Object[] specificInterceptors
                        = getAdvicesAndAdvisorsForBean
                                    (bean.getClass(), beanName, null);
    //如果通知不为空
    //protected static final Object[] DO_NOT_PROXY = null;
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        Object proxy = createProxy(bean.getClass(), 
                                   beanName, 
                                   specificInterceptors, 
                                   new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
​
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey)))判断是否在不需要代理的集合里

if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)),这两行判断跟上面的一样,不解释。

如果这两个判断都不成立,下面的代码就是代理的创建!创建!创建!

由于本文只探讨时机,不探讨具体的创建代理的过程的源码,创建代理的过程的源码会在后续文章中更新。

参考链接:blog.csdn.net/qq_41084438…