Bean后置处理器 - SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
示例
@Component public class IndexA { @Autowired IndexB bbb; public IndexA() { System.out.println("IndexA constructor..."); } public void printf(){ System.out.println("indexA printf : "); System.out.println("indexB --> " + (bbb == null ? null : bbb.getClass().getName())); } } @Component public class IndexB { @Autowired IndexA aaa; public IndexB() { System.out.println("IndexB constructor..."); } public void printf(){ System.out.println("indexB printf : "); System.out.println("indexA --> " + (aaa == null ? null : aaa.getClass().getName())); } } @Configuration @ComponentScan({ "com.study.ioc.cyc" }) public class StartConfig { }
测试代码:
public static void main(String[] args) { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(StartConfig.class); IndexA a = ac.getBean(IndexA.class); System.out.println("spring's indexA --> " + a.getClass().getName()); a.printf(); System.out.println("======================"); IndexB b = ac.getBean(IndexB.class); System.out.println("spring's indexB --> " + b.getClass().getName()); b.printf(); }
运行结果:
对于这种存在循环依赖的情况, 其大致过程是这样的:
1. 实例化 IndexA
2. 对 IndexA 进行属性注入, 此时发现 属性 IndexB
3. 实例化 IndexB
4. 对 IndexB 进行属性注入, 此时又发现了属性 IndexA
5. 对 IndexA 执行 getSingleton("indexA") (此时, 会调用后置处理器 SmartInstantiationAwareBeanPostProcessor), 拿到 IndexA
6. 回到 IndexB 属性注入的地方, 然后对 IndexB 进行初始化
7. IndexB 变成了一个 bean, 回到 IndexA 属性注入的地方, 然后对 IndexA 进行初始化
getSingleton的关键代码为:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
此时, allowEarlyReference = true, 是写死的
@Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { //从map中获取bean如果不为空直接返回,不再进行初始化工作 //讲道理一个程序员提供的对象这里一般都是为空的 //1.先从一级缓存获取 Object singletonObject = this.singletonObjects.get(beanName); //2.如果没获取到, 且 bean 还在创建中时 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { //3.再从二级缓存中获取 singletonObject = this.earlySingletonObjects.get(beanName); //4. 还没获取到, 且允许循环依赖时 if (singletonObject == null && allowEarlyReference) { //5. 最后从三级缓存中获取 对象的工厂, 通过 getObject 来获取对象 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
看到这里, 需要回到
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
看一句关键代码:
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"); } //这里创建了一个匿名的 ObjectFactory 实现类, 他是一个工厂, 可以用来获取对象 //addSingletonFactory中, 将这个工厂放到 singletonFactories 中去了. singletonFactories 是spring的三级缓存 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); }
singletonFactory.getObject() 调用的, 其实是 这里的 getEarlyBeanReference() 方法
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; }
前面有看到过, SmartInstantiationAwareBeanPostProcessor 可以用来选择构造函数, 那么这里, 他还可以用来暴露 bean 的早期引用.
此例中, 就是暴露 IndexA 的早期引用. 此时 IndexA 还没有进行初始化, 是一个半成品.
如果有对 IndexA 进行 AOP , 那么也会在这里进行一次代理. 将代理过的对象暴露给 IndexB.
还是通过调试的方式, 来确定下, 这边有那些后置处理器能满足条件:
1. ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
2. AutowiredAnnotationBeanPostProcessor
ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
由其父类实现:
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#getEarlyBeanReference
@Override public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { return bean; }
ImportAwareBeanPostProcessor 在 创建 bean 的这整个过程中, 出现的频率蛮高的, 但是大部分都是来凑热闹的.
AutowiredAnnotationBeanPostProcessor
也是由其父类实现:
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#getEarlyBeanReference
@Override public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { return bean; }
从这里可以看出, 正常情况下(不需要代理时), 该是什么, 这里就返回什么, 不会对 bean 进行任何操作
上面说, 在这个后置处理器的处理里面, 可能会产生代理, 为了印证这个问题, 需要对实例代码进行一些小的修改:
@Component @Aspect public class Aopa { @Pointcut("execution(* com.study.ioc.cyc.IndexA.*(..))") public void pointCutMethodA() { } @Before("pointCutMethodA()") public void beforeA() { System.out.println("before invoke indexA.*() method -- Aopa"); } } @EnableAspectJAutoProxy @Configuration @ComponentScan({ "com.study.ioc.cyc" , "com.study.ioc.aop" }) public class StartConfig { }
此时, 再到方法里面进行调试, 会发现多出来一个后置处理器, 变成了三个:
1. ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
2. AnnotationAwareAspectJAutoProxyCreator
3. AutowiredAnnotationBeanPostProcessor
AnnotationAwareAspectJAutoProxyCreator
@Override public Object getEarlyBeanReference(Object bean, String beanName) { Object cacheKey = getCacheKey(bean.getClass(), beanName); this.earlyProxyReferences.put(cacheKey, bean); return wrapIfNecessary(bean, beanName, cacheKey); }
进 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; } 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); 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; }
这里看到, 有一个创建代理的方法. 确实是通过这里, 产生了代理方法.
此例中, 如果aop里面, 把 IndexB 也加进去, 那么 IndexB 是不是也会在这里进行代理呢?
答案是否定的. IndexB在此例中, 不会进这个方法的. 对于 IndexB 来说, 其实是一个正常的创建过程.
IndexB 的代理, 会在别的地方进行.(initializeBean中 - 初始化之后的后置处理器中完成代理)
这个在后面就能看到