前面的文章主要集中在分析Spring IOC容器部分的原理,這部分的核心邏輯是和bean建立及管理相關,對於單例bean的管理,從建立好到緩存起來再到銷燬,其是有一個完整的生命週期,而且Spring也在整個bean的建立過程當中提供了多處接口供使用者本身擴展,本文就來梳理一下Spring中的bean生命週期。spring
對於prototype做用域的Bean,Spring容器僅僅負責建立,當容器建立了Bean實例以後,Bean實例徹底交給客戶端代碼管理,容器再也不跟蹤其生命週期。每次客戶端請求prototype做用域的Bean時,Spring都會產生一個新的實例,Spring容器沒法知道它曾經創造了多少個prototype做用域的Bean,也無從知道這些prototype做用域的Bean何時纔會銷燬。所以,Spring沒法管理prototype做用域的Bean。數據庫
對於singleton做用域的Bean,每次客戶端代碼請求時,都返回同一個共享實例,客戶端代碼不能控制Bean的銷燬,Spring容器負責跟蹤Bean實例的產生、銷燬。Spring容器能夠在建立Bean以後,進行某些通用資源的申請;還能夠在銷燬Bean實例以前,先回收某些資源,好比數據庫鏈接等。緩存
先來看一下Spring Bean的完整生命週期,從建立Spring容器開始,直到最終Spring容器銷燬Bean:app
咱們將Spring容器中Bean的生命週期級別分爲四級,分別是:ide
Bean自身的方法:調用構造函數實例化bean,調用setter設置屬性,調用init-method,destroy-method。函數
Bean級生命週期方法:如BeanNameAware,BeanFactoryAware,InitializingBean和DisposableBean,這些接口由bean直接實現。post
容器級生命週期接口方法:有InstantiationAwareBeanPostProcessor和BeanPostProcessor這兩個接口實現,通常稱他們的實現類爲後處理器。實現類獨立於bean,以容器附加裝置的形式註冊到spring當中。當spring建立任何bean時,這些後處理器都會發生做用,因此後處理器的影響是全局性的。固然,用戶能夠經過合理的編寫後處理器,讓其僅對感興趣的bean進行加工處理。測試
Bean級生命接口和容器級生命接口是個性和共性辯證統一思想的體現。前者解決bean的個性化處理的問題,後者解決容器中某些bean共性化處理的問題。ui
工廠級生命週期接口方法(BeanFactoryPostProcessor接口的實現類),能夠對bean的定義(配置元數據)進行處理。也就是說,Spring IoC容器容許BeanFactoryPostProcessor在容器實際實例化任何其它的bean以前讀取配置元數據,並有可能修改它。this
下面經過一個例子來實際體驗一下bean的生命週期中的各個關鍵接口方法的調用。FruitStore類中定義了Bean自身方法以及Bean級生命週期方法:
public class FruitStore implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean{ private String name; private String address; private ApplicationContext applicationContext; private String beanName; public FruitStore() { System.out.println("[FruitStore]--構造器"); } /** Bean自身方法 **/ // 經過<bean>的init-method屬性指定的初始化方法 public void myInit() { System.out.println("[Bean自身方法] [init-method] 初始化方法..."); } // 經過<bean>的destroy-method屬性指定的初始化方法 public void myDestory() { System.out.println("[Bean自身方法] [destroy-method] 銷燬方法..."); } public void sayHello() { System.out.println("[Bean自身方法] sayHello..."); } /** Bean級生命接口方法begin **/ public void setName(String name) { this.name = name; System.out.println("[Bean級接口] [注入屬性] 注入屬性name..."); } public void setAddress(String address) { this.address = address; System.out.println("[Bean級接口] [注入屬性] 注入屬性address..."); } // DiposibleBean接口方法 public void destroy() throws Exception { System.out.println("[Bean級接口] 銷燬方法..."); } // InitializingBean接口方法 public void afterPropertiesSet() throws Exception { System.out.println("[Bean級接口] [InitializingBean接口] 初始化方法..."); } // BeanFactoryAware接口方法 public void setApplicationContext(ApplicationContext arg0) throws BeansException { this.applicationContext = arg0; System.out.println("[Bean級接口] [ApplicationContextAware接口] 注入Spring容器ApplicationContext..."); } // BeanNameAware接口方法 public void setBeanName(String name) { this.beanName = name; System.out.println("[Bean級接口] [BeanNameAware接口] 注入beanName..."); } @Override public String toString() { return "FruitStore [name=" + name + ", address=" + address + ", applicationContext=" + applicationContext + ", beanName=" + beanName + "]"; } }
分別實現兩種容器級接口,首先是InstantiationAwareBeanPostProcessor接口:
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { public MyInstantiationAwareBeanPostProcessor() { super(); System.out.println("[容器級接口] [InstantiationAwareBeanPostProcessor實現類]--構造器"); } // 實例化Bean以前調用 @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { System.out.println("[容器級接口] [InstantiationAwareBeanPostProcessor實現類]--實例化Bean以前調用"); return null; } // 實例化Bean以後調用 @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("[容器級接口] [InstantiationAwareBeanPostProcessor實現類]--實例化Bean以後調用"); return true; } // 初始化Bean以前調用 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("[容器級接口] [InstantiationAwareBeanPostProcessor實現類]--初始化Bean以前調用"); return bean; } // 初始化Bean以後調用 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("[容器級接口] [InstantiationAwareBeanPostProcessor實現類]--初始化Bean以後調用"); return bean; } // 設置某個屬性時調用 @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { System.out.println("[容器級接口] [InstantiationAwareBeanPostProcessor實現類]--實例化Bean以後,設置某個屬性時調用"); return pvs; } }
而後實現BeanPostProcessor接口:
public class MyBeanPostProcessor implements BeanPostProcessor{ public MyBeanPostProcessor() { System.out.println("[容器級接口] [MyBeanPostProcessor實現類]--構造器"); } // 初始化Bean以前調用 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("[容器級接口] [BeanPostProcessor實現類]--初始化Bean以前調用"); return bean; } // 初始化Bean以後調用 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("[容器級接口] [BeanPostProcessor實現類]--初始化Bean以後調用"); return bean; } }
工廠級生命週期接口方法(BeanFactoryPostProcessor接口的實現類):
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{ public MyBeanFactoryPostProcessor() { super(); System.out.println("[工廠級接口] [BeanFactoryPostProcessor實現類]--構造器"); } public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException { System.out.println("[工廠級接口] [BeanFactoryPostProcessor實現類] Spring容器加載以後,全部Bean實例化以前調用"); // 重寫Person Bean的phone屬性 BeanDefinition bd = arg0.getBeanDefinition("fruitStore"); bd.getPropertyValues().addPropertyValue("name", "papaya-mangos"); } }
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- 定義工廠級生命週期接口. --> <bean id="beanFactoryPostProcessor" class="spring.source.MyBeanFactoryPostProcessor"></bean> <!-- 定義容器級生命週期接口. --> <bean id="beanPostProcessor" class="xxx.xxx"></bean> <bean id="instantiationAwareBeanPostProcessor" class="xxx.xxx"></bean> <!-- 定義Bean自身及Bean級生命週期接口. --> <bean id="fruitStore" class="xxx.xxx" init-method="myInit" destroy-method="myDestory" scope="singleton"> <property name="name" value="永輝超市"></property> <property name="address" value="杭州"></property> </bean> </beans>
測試代碼:
public static void main(String[] args) { try{ System.out.println("============================== 如今開始初始化容器. =============================="); ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("\r\n============================== 容器初始化成功. =============================="); //獲得Preson,並使用 FruitStore fruitStore = ctx.getBean("fruitStore",FruitStore.class); fruitStore.sayHello(); System.out.println(fruitStore); System.out.println("\r\n============================== 如今開始關閉容器! =============================="); ctx.close(); }catch (Exception e){ e.printStackTrace(); } }
運行結果爲:
這裏再分析上述運行結果:
準備Spring容器
實例化Bean
注入依賴關係
初始化Bean
使用Bean
銷燬Bean
本文咱們總結了Spring中Bean的生命週期,主要有以下流程:
總結了常見的配置Bean生命週期的方式主要有三種:
經過<bean>的init-method和destroy-method屬性配置方式爲bean指定初始化和銷燬的方法,採用這種方式的效果和經過實現InitializingBean,DisposableBean接口所達到的效果是徹底相同的,可是採用前者配置方式可使bean不須要和特定的spring接口綁定,前者是和spring「不對應用程序類做任何限制」的理論相符合的。
而像BeanPostProcessor這類的後處理器接口則不同,它不要求bean去繼承它,而是徹底像插件同樣註冊到spring容器中,爲容器提供額外的功能。spring充分利用了BeanPostProcessor對bean進行加工處理(SpringAOP以此爲基礎,後面會細說)。
spring做爲ioc容器其核心功能就是管理bean的建立以及bean之間的依賴關係,再進一步就是說spring管理bean的整個生命週期,從實例化到初始化,再到緩存建立好的bean以及銷燬bean。在這個過程當中,spring提供了多種方式(如上所述),使得用戶能夠在bean的整個生命週期中方便地作一些自定義的操做。這也是spring中體現出來的一種優秀的設計方法論,easy to change,對擴展開放。