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

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

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

参考链接:https://blog.csdn.net/qq_41084438/article/details/129801085

image.png

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

```java 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中的如下代码

java 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之前就创建好代理对象。

java //给Bean后置处理器一个机会,返回一个替代目标对象的代理对象。 //就在这里 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) {    //注意如果有 InstantiationAwareBeanPostProcessor类型的接口    //并返回了自定义对象 这里会直接返回    return bean; } //如果上面直接返回了bean 下面的doCreateBean就不会执行 Object beanInstance = doCreateBean(beanName, mbdToUse, args);

java // 给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

```java 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);

```java protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction) () -> { 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

```java @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的逻辑。

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

原来postProcessBeforeInitialization啥也不做呀。

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

java @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)),这两行判断跟上面的一样,不解释。

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

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

参考链接:https://blog.csdn.net/qq_41084438/article/details/129801085

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值