一個Spring框架的應用中會有涉及到多個bean,各種各樣配置形式的bean。 這些bean是按照什么順序加載的?
如果在執行一些初始化或者其他操作時需要依賴這些bean的執行順序,那么就得對這些bean的加載順序有所了解。
網上查閱相關資料轉發如下:
總結性話語見:http://wolfdream.iteye.com/blog/1172821
spring加載Bean順序【轉】
一,單一Bean
- 裝載
1. 實例化;
2. 設置屬性值;
3. 如果實現了BeanNameAware接口,調用setBeanName設置Bean的ID或者Name;
4. 如果實現BeanFactoryAware接口,調用setBeanFactory 設置BeanFactory;
5. 如果實現ApplicationContextAware,調用setApplicationContext設置ApplicationContext
6. 調用BeanPostProcessor的預先初始化方法;
7. 調用InitializingBean的afterPropertiesSet()方法;
8. 調用定制init-method方法;
9. 調用BeanPostProcessor的后初始化方法;
- spring容器關閉
1. 調用DisposableBean的destroy();
2. 調用定制的destroy-method方法;
二,多個Bean的先后順序
- 優先加載BeanPostProcessor的實現Bean
- 按Bean文件和Bean的定義順序按bean的裝載順序(即使加載多個spring文件時存在id覆蓋)
- “設置屬性值”(第2步)時,遇到ref,則在“實例化”(第1步)之后先加載ref的id對應的bean
- AbstractFactoryBean的子類,在第6步之后,會調用createInstance方法,之后會調用getObjectType方法
- BeanFactoryUtils類也會改變Bean的加載順序
以下內容轉自:http://blog.csdn.net/sky_ground/article/details/63688397
解答以下疑惑:
- Spring配置文件里bean,究竟是按什么樣的順序加載呢?
- Spring項目在部署時,究竟創建了多少個beanFactory呢?按什么順序創建?
長話短說,總結成如下幾點:
Rule1:
首先讀取WEB-INF/web.xml文件,該文件內一般會配置spring-config和spring-mvc。按順序加載對應的xml文件。
Rule2:
若web.xml中還有除springmvc和默認的servlet之外的servlet(如servlet-test),那么這些servlet會按照定義的順序執行,但一定是在默認servlet之后,springmvc之前執行,並且,若這些servlet都會分別對應一個ApplicationContext,當然也意味着分別擁有一個beanFactory。這些ApplicationContext(包括springmvc的那個),他們的parent ApplicationContext均是默認servlet對應的那個ApplicationContext(Root ApplicationContext)。
因此,若springmvc里的某個Controller嘗試通過auto wire注解來注入servlet-test里面的service,那么在運行時會拋出”Could not autowire field …”異常,因為spring從springmvc那個servlet中的beanFactory(包括其父beanFactory)中找不到對應的bean。
Rule3:
在加載某個包含bean的xml文件時,按照bean的類型1)BeanFactoryPostProcessor類的bean;2)BeanPostProcessor類的bean;3)普通bean,包括import進來的(bean標簽和scan標簽指定的);的順序進行加載。同類型的bean按照定義順序加載。所有bean默認是單例的。
因此,對於BeanFactoryPostProcessor和BeanPostProcessor類型的bean,即使被放置在最后面,也會先加載哦。這種設計還是挺人性化的^_^
Rule4:
component-scan生成的bean的默認id是類名(首字母小寫),例如testService1。
<bean>標簽生成的bean的默認id是: 包名.類名#數字,例如qk.spring.beanFactory.service1.TestService1#0
如果component-scan和bean標簽生成的bean有沖突(即bean的id相同),並且都是單例(默認是單例),那么不會重復創建,只保留最先創建出來的那個。