這個問題看似簡單實則坑多。
- 1、很早以前有人告訴我說,spring是在你使用該bean的時候,通過動態代理給你實例化出來的。
- 2、後來又有人告訴我說,spring是在容器啓動的時候就將bean都給你實例化好了。
那麼究竟哪個正確呢?其實這麼回答都不正確,spring對bean的初始化其實是有條件的。
首先判斷是單例還是多例,如果是多例的情況下,肯定是在你第一次使用該bean的時候初始化無疑。
但是如果是單例的情況下又分爲兩種情況:
- 一是當你
lazy-init
懶加載設置爲true
時是在你第一次使用的時候實例化;第一次使用包括的範圍是此對象被其它bean
引用也算第一次使用,所以即使你設置lazy-init
爲ture
只要你的此bean
被引用或者注入也會被初始化。 - 二是
lazy-init
懶加載爲false
時(這也是spring默認值
)是在spring容器啓動時進行實例化。
以下我們來看下spring實例化bean的源碼你就知道了
查看AbstractApplicationContext.refresh()
方法中實例化所有非懶加載的bean
過程即
這個方法finishBeanFactoryInitialization
查看此方法最後一行beanFactory.preInstantiateSingletons();
實際調用此方法我們來看此單例實例化過程
爲DefaultListBeanFactory.preInstantiateSingletons
源碼如下
public void preInstantiateSingletons() throws BeansException {
//此處省略無數行代碼。。。。。
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//此處做出了判斷必須是非抽象的並且必須是單例的並且必須是非懶加載的。
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//此處省略無數行代碼
}
}
//此處省略無數行代碼
}
從以上代碼的循環中的條件我們不難看出容器啓動過程中會實例化的bean
只有滿足以下三個條件的bean
:
- 非抽象的
- 單例的
- 非懶加載的