Spring提供了一些接口來提供一些方法,體現了bean對象在Spring容器中的生命周期
具體的過程可以體現為:
讀取權限類名->構建一個類對象->用這個類對象通過無參構造器newInstance()構建對象
↓
調用set方法注入依賴
↓
如果這個Bean已經實現了BeanNameAware接口
調用它實現的setBeanName(String name)方法
此處傳遞的就是Spring配置文件中Bean的name值
↓
如果這個Bean已經實現了BeanFactoryAware接口
容器會調用它實現的setBeanFactory方法
該方法接收的參數就是當前容器本身(可以用這個方式來獲取其它Bean)
↓
如果這個Bean已經實現了ApplicationContextAware接口
容器會調用setApplicationContext方法,該步和第四步類似
↓
如果有類實現了BeanPostProcessor接口並且注入到容器中
那么會執行該類中重寫的postProcessBeforeInitialization(Object bean, String beanName)
這個方法在自己定義的init-method之前調用
↓
執行自己在xml配置文件中注入對象定義的init-method方法
↓
如果有類實現了BeanPostProcessor接口並且注入到容器中
那么會執行該類中重寫的postProcessAfterInitialization(Object bean, String beanName)
這個方法在自己定義的init-method之后調用
↓
當Bean不再需要時,會經過清理階段
如果Bean實現了DisposableBean這個接口
會調用那個其實現的destroy()方法
↓
最后,如果這個Bean的Spring配置中配置了destroy-method屬性
會自動調用其配置的銷毀方法
設計一個類來測試bean對象的生命周期
/*這里面測試的是spring容器中bean對象完整的生命周期*/ public class Life implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,DisposableBean{ private String name; public String getName() { return name; } //1、容器創建該Bean的對象 public Life() { System.out.println("第一步,創建對象"); } //2、容器給這個Bean對象注入依賴 public void setName(String name) { System.out.println("第二步,依賴注入"); this.name = name; } //3、如果這個Bean已經實現了BeanNameAware接口,容器會調用它實現的setBeanName(String)方法,此處傳遞的就是Spring配置文件中Bean的id值 @Override public void setBeanName(String name) { System.out.println("第三步,調用setBeanName方法,因為bean類實現了BeanNameAware"); } //4、如果這個Bean已經實現了BeanFactoryAware接口,容器會調用它實現的setBeanFactory方法 //該方法接收的參數就是當前容器本身(可以用這個方式來獲取其它Bean) @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("第四步,調用setBeanFactory方法,因為bean類實現了BeanFactoryAware"); } //5、如果這個Bean已經實現了ApplicationContextAware接口,容器會調用setApplicationContext方法,該步和第四步類似,ApplicationContext是BeanFactory的子接口,有更多的實現方法 @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { System.out.println("第五步,調用setApplicationContext方法,因為bean類實現了ApplicationContextAware"); } //9、當Bean不再需要時,會經過清理階段,如果Bean實現了DisposableBean這個接口,會調用那個其實現的destroy()方法; @Override public void destroy() throws Exception { System.out.println("第九步,調用destroy方法,因為bean類實現了ApplicationContextAware"); } /** *注意下面的兩個方法是自定義的初始化和銷毀對象方法 *需要在注入對象的時候指定init-method="..",destroy-method="..." *注意方法的執行順序 *init-method在各個初始化方法執行之后才執行 *destroy-method在最后執行 */ //7、如果Bean在Spring配置文件中配置了init-method屬性則會自動調用其配置的初始化方法 //init-method="myInit" public void myInit(){ System.out.println("第七步,調用myInit方法,因為bean在xml中的配置里面使用了init-method屬性來指定初始化方法"); } //10、最后,如果這個Bean的Spring配置中配置了destroy-method屬性,會自動調用其配置的銷毀方法 public void myDestroy(){ System.out.println("第十步,調用myDestroy方法,因為bean在xml中的配置里面使用了destroy-method屬性來指定初始化方法"); } }
再寫一個類用來實現BeanPostProcessor接口
/*注意:需要把這個類注冊到spring的容器中,才能生效*/ public class MyBeanPostProcessor implements BeanPostProcessor{ //這個方法在自己定義的init-method之前調用 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("第六步,調用postProcessBeforeInitialization方法,因為spring容器中注冊了BeanPostProcessor接口的實現類"); return bean; } //這個方法在自己定義的init-method之后調用 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("第八步,調用postProcessAfterInitialization方法,因為spring容器中注冊了BeanPostProcessor接口的實現類"); return bean; } }
我們在配置文件中進行一個配置
<bean class="com.briup.ioc.life.MyBeanPostProcessor"></bean> <bean name="life" class="Life" init-method="myInit" destroy-method="myDestroy"> <property name="name" value="張三"></property> </bean>
以上是完整的生命周期,下面來說的是非完整的生命周期,一般來說在開發的時候沒有必要每次都讓一個對象都具有完整生命周期的方法
/*這里面測試的是spring容器中bean對象普通的聲明周期*/ /*Bean中不實現spring提供的任何接口,之后項目大多數Bean是這種情況*/ public class LifeBean{ private String name; public LifeBean(){ System.out.println("LifeBean() 構造器"); } public String getName() { return name; } public void setName(String name) { System.out.println("setName() 方法"); this.name = name; } public void init(){ System.out.println("init方法執行"); } public void destory(){ System.out.println("destory方法執行"); } }
生命周器對於單例對象和非單例對象來說,非單例對象在創建后會脫離容器的控制
單例管理的對象:
1.默認情況下,spring在讀取xml文件的時候,就會創建對象
2.進行依賴注入,如果有依賴的話
3.會去調用init-method=".."屬性值中所指定的方法,如果有該配置的話
4.Bean對象可以被正常使用
5.對象在被銷毀的時候,會調用destroy-method="..."屬性值中所指定的方法,如果有該配置的話
注意1:調用container.destroy()方法會銷毀單例對象
注意2:lazy-init="true",可以讓這個Bean對象在第一次被訪問的時候創建,而不是讀取xml文件就被創建
注意3:因為是單例,所以該對象只會被創建一次
非單例管理的對象:
1.使用這個對象的時候,spring容器會創建這個對象
2.進行依賴注入,如果有依賴的話
3.會去調用init-method=".."屬性值中所指定的方法,如果有該配置的話
4.Bean對象可以被正常使用
注意1:spring容器不會銷毀非單例對象
注意2:因為是非單例,所以每次使用都會創建一個新的Bean對象
非單例也是當獲取對象的時候再加載,不會受到Spring容器的管理