示例 @Component public class IndexA { @Autowired IndexB bbb; public IndexA() { System.out.println("IndexA constructor..."); } public void printf(){ Syst ...
示例
@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中 - 初始化之後的後置處理器中完成代理)
這個在後面就能看到