Spring創建單例Bean關鍵源碼分析


在上一篇文章中,我一步步分析了使用 BeanFactory 獲取並創建 Bean 的過程,並且解釋了 Spring 是如何解決循環依賴的?

類繼承結構

  • DefaultSingletonBeanRegistry 負責單例的注冊
  • AbstractAutowireCapableBeanFactory 自動裝配工廠

創建Bean核心過程簡化

其中,橙色為 protected 方法,綠色為 public 方法

  1. getBean 獲取並創建 Bean
  2. doGetBean 具體的獲取方法
  3. doCreateBean 具體的創建 Bean 的方法
  4. populateBean 填充屬性
  5. 填充屬性時,有可能需要獲取並創建新的 Bean,再次回到第 1 步

接口 BeanFactory 中的 getBean 方法有 5 個:

其中 2 個以對象類型為參數的 getBean 方法是由 DefaultListableBeanFactory 實現的。

// 返回與給定對象類型唯一匹配的bean實例(如果有)
public <T> T getBean(Class<T> requiredType) throws BeansException { // ...(省略) }
// 返回指定bean的實例,該實例可以是共享的,也可以是獨立的。
// 允許指定顯式構造函數參數/工廠方法參數,並覆蓋bean定義中指定的默認參數(如果有)
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException { // ...(省略) }

剩下 3 個由 AbstractBeanFactory 實現,並且都調用了 doGetBean 方法

public Object getBean(String name) throws BeansException {
      return doGetBean(name, null, null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
      return doGetBean(name, requiredType, null, false);
}
public Object getBean(String name, Object... args) throws BeansException {
      return doGetBean(name, null, args, false);
}

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException {
      return doGetBean(name, requiredType, args, false);
}

Spring 創建俯瞰圖


這個是我自己畫的一張Spring 創建單例 Bean 的流程圖,看不懂先別着急,讓我接下來細細分說。

getSingleton

獲取單例的兩個方法都是在 DefaultSingletonBeanRegistry 中實現的。

getSingleton(beanName, singletonFactory)

首先介紹的是參數為 ObjectFactory 的getSingle方法:

/**
 * 返回以給定名稱注冊的(原始)單例對象,
 * 如果尚未注冊,則創建並注冊一個新的。
 */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {  // ...(省略) }

該方法內的重要方法如圖所示:

beforeSingletonCreation(String beanName)afterSingletonCreation(String beanName) 一個標識創建開始,一個標識創建結束,與之相關的還有一個方法

/**
 * 返回指定的單例bean當前是否正在創建中
 */
public boolean isSingletonCurrentlyInCreation(String beanName) {
	return this.singletonsCurrentlyInCreation.contains(beanName);
}

其中,singletonsCurrentlyInCreation 是保存正在創建中的單例bean的集合。

我們知道,調用該 getSingleton 方法是在 doGetBean 中,且其匿名內部類調用的是 createBean 方法,該方法被 AbstractAutowireCapableBeanFactory 覆寫。源碼如下

// AbstractBeanFactory.class
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
      // ... 省略
      // Create bean instance.
      if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
                  try {
                        return createBean(beanName, mbd, args);
                  }
		  catch (BeansException ex) {
			// Explicitly remove instance from singleton cache: It might have been put there
			// eagerly by the creation process, to allow for circular reference resolution.
			// Also remove any beans that received a temporary reference to the bean.
			destroySingleton(beanName);
			throw ex;
		  }
	    });
	    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
      }
      // ... 省略
}
// 需要 AbstractBeanFactory 的子類覆寫,最終由 AbstractAutowireCapableBeanFactory 實現
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException;

addSingleton(String beanName, Object singletonObject) 方法將給定的單例對象添加到該工廠的單例緩存中。
即添加到singletonObjects 單例池中。

getSingleton(beanName, allowEarlyReference)

/**
 * 返回以給定名稱注冊的(原始)單例對象。
 * 檢查已經實例化的單例,並且還允許對當前創建的單例的早期引用(解決循環引用)。
 */
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

這個方法涉及到 DefaultSingletonBeanRegistry 的三個集合:

  • singletonObjects 是單例的緩存,可以避免重復創建單例
  • earlySingletonObjects 是未完成單例的緩存,用來解決循環依賴
  • singletonFactories 是單例工廠集,也是用來解決循環依賴的,當方法參數 allowEarlyReference 為 true 時才會取出對應的單例工廠,執行創建,並且將單例的早期引用放入未完成單例集中。


如圖所示,getSingleton(String beanName) 方法是目前唯一允許創建單例的早期引用的方法。

@Override
@Nullable
public Object getSingleton(String beanName) {
      return getSingleton(beanName, true);
}

doCreateBean

接下來,我們關注到實際負責創建 Bean 的方法 doCreateBeancreateBean 是由 AbstractAutowireCapableBeanFactory 覆寫的,doCreateBean 也是該類的方法

  • createInstance 實例化Bean
  • addSingletonFactory 是在發生循環依賴的情況下,添加 ObjectFactory 到單例工廠集singletonFactories
  • populateBean 填充屬性
  • initializeBean 初始化Bean

初始化Bean

初始化 Bean 又分為3個步驟:

  • applyBeanPostProcessorsBeforeInitialization 在執行初始化方法之前,進行前置操作
  • invokeInitMethods 執行初始化方法
    最常見的就是實現 InitializingBean 接口:
public interface InitializingBean {
	/**
	 * 此方法允許Bean實例在設置所有Bean屬性后執行其整體配置的驗證和最終初始化。
	 */
	void afterPropertiesSet() throws Exception;
}
  • applyBeanPostProcessorsAfterInitialization 在執行初始化方法之后,執行后置操作

以下是一個簡單的代碼示例:

// 實現初始化方法的類
public class MessageList implements InitializingBean {

    private List<String> messages = new ArrayList<>();

    public MessageList() {
        messages.add("createInstance");
    }

    public void addMessage(String msg) {
        messages.add(msg);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        messages.add("afterPropertiesSet");
    }

    public void printAllMessages() {
        for (String message : messages) {
            System.out.println(message);
        }
    }
}

測試類:

public class BeanFactoryTest {

    @Test
    public void messageListTest() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof MessageList) {
                    ((MessageList) bean).addMessage("postProcessBeforeInitialization");
                }
                return bean;
            }

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof MessageList) {
                    ((MessageList) bean).addMessage("postProcessAfterInitialization");
                }
                return bean;
            }
        });
        RootBeanDefinition def = new RootBeanDefinition(MessageList.class);
        factory.registerBeanDefinition("messageList", def);
        MessageList bean = factory.getBean(MessageList.class);
        bean.printAllMessages();
    }
}

輸出結果:

循環依賴的后置處理

假設 AService 和 BService 構成循環依賴

public class AService {
    private BService bService;

    public BService getBService() {
        return bService;
    }
    public void setBService(BService bService) {
        this.bService = bService;
    }
}

public class BService {
    private AService aService;

    public AService getAService() {
        return aService;
    }

    public void setAService(AService aService) {
        this.aService = aService;
    }
}

然后我們寫出測試類

public class ABServiceBeanFactoryTest {

    @Test
    public void test() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.addBeanPostProcessor(new SmartInstantiationAwareBeanPostProcessor() {
            @Override
            public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
                if (bean instanceof AService) {
                    return new AService$Proxy((AService) bean);
                }
                return bean;
            }

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                return bean;
            }
        });
        {
            RootBeanDefinition definition = new RootBeanDefinition(AService.class);
            definition.setPropertyValues(new MutablePropertyValues().add("bService", new RuntimeBeanReference(BService.class)));
            factory.registerBeanDefinition("aService", definition);
        }
        {
            RootBeanDefinition definition = new RootBeanDefinition(BService.class);
            definition.setPropertyValues(new MutablePropertyValues().add("aService", new RuntimeBeanReference(AService.class)));
            factory.registerBeanDefinition("bService", definition);
        }
        AService bean = factory.getBean(AService.class);
        Assert.assertEquals(bean, bean.getBService().getAService());
    }

    public static class AService$Proxy extends AService {

        private AService aService;

        public AService$Proxy(AService aService) {
            this.aService = aService;
        }

        @Override
        public BService getBService() {
            return aService.getBService();
        }
    }
}

BeanPostProcessor 接口對循環依賴不起作用

第一個值得注意的點,對於循環依賴 aService 而言,只有 SmartInstantiationAwareBeanPostProcessor 才能夠后置處理 AService 的未完成實例,原因在 getEarlyBeanReference 方法中

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
	Object exposedObject = bean;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
                        // 只有 SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference 才能后置處理未完成的實例
			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
				exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
			}
		}
	}
	return exposedObject;
}

為什么 postProcessAfterInitialization 對循環依賴對象不起作用?

第二點,如果增加了 postProcessBeforeInitialization(Object bean, String beanName)postProcessAfterInitialization(Object bean, String beanName) 后置處理方法,bean對象都是 AService 而不是 AService$Proxy ,但是最后 getBean 返回的結果是 AService$Proxy。

如圖所示,postProcessAfterInitialization 傳入的 Bean 對象是 AService。

如圖所示,最終返回的是 AService$Proxy 對象,這是怎么做到的?
答案就在 AbstractAutowireCapableBeanFactory#doCreateBean 方法中,請看下圖

結論:在發生循環依賴時,無論你在 postProcessBeforeInitializationpostProcessAfterInitialization 做何種后置處理,最終暴露給 BService 對象使用的引用,以及最后 getBean 返回的都將是 getEarlyBeanReference 后置處理后的 AService 對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM