Spring bean 的生命週期很容易理解。實例化 bean 時,可能須要執行一些初始化以使其進入可用 (Ready for Use)狀態。相似地,當再也不須要 bean 並將其從容器中移除時,可能須要進行一些清理,這就是它的生命週期java
上一篇文章 面試還不知道BeanFactory和ApplicationContext的區別? 中說明了接口 Beanfactory 和 Applicationcontext 能夠經過 T getBean(String name, Class<T> requiredType)
方法從 Spring 容器中獲取bean,區別是,前者是懶加載形式,後者是預加載的形式。那麼問題來了:面試
這些 Spring Beans 是怎麼生成出來的呢?spring
在正式回答這個問題以前,先解答一些有關 Java Bean, Spring Bean 和 Spring IoC 容器這些概念性的疑惑,我但願經過下面這個例子形象說明這些問題:編程
小學生 (Java Bean)經過提交資料申請(元數據配置)加入了少先隊(Spring Ioc 容器),學習了一些精神與規定以後,變成了少先隊員(Spring Bean)設計模式
從這裏能夠看出,Java Bean 和 Spring Bean 都是具備特定功能的對象,小學生仍是那個小學生,只不過加入了少先隊以後有了新的身份,新的身份要按照組織 (Spring Ioc)的規定履行特定義務網絡
來看下圖加深一下了解 框架
首先要有容器,實例化 Spring Ioc 容器是很是簡單的,接口 org.springframework.context.ApplicationContext
表示Spring IoC容器,負責實例化,配置和組裝上述 bean。 容器經過讀取配置元數據獲取有關要實例化,配置和組裝的對象的指令。 配置元數據一般以XML,Java 註解或代碼的形式表示。 它容許你本身表達組成應用程序的對象以及這些對象之間豐富的相互依賴性,好比這樣:ide
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring.xml", "spring1.xml"});
複製代碼
有了容器,咱們須要作哪些處理,使其內部對象變爲
Ready for Use
的狀態?
咱們須要經過 Spring 容器實例化它們,Spring 爲咱們提供了三種方式:post
Spring 爲咱們提供了 InitializingBean
接口學習
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
複製代碼
咱們能夠經過實現 InitializingBean
接口,在其惟一方法 afterPropertiesSet
內完成實例化的工做,可是 Spring Framework 官方並不建議咱們經過這種方法來完成 Bean 的實例化,這是一種強耦合的方式,咱們看到框架層面纔會用到這個方法。
這種方式是 Spring 很是提倡的一種方式,咱們一般將其標記在方法上便可,一般習慣將這個方法起名爲 init()
@PostConstruct
public void init() {
System.out.println("Inside init() method...");
}
複製代碼
你應該見過這種初始化方式:
public class MyClass {
public void init() {
// perform post-creation logic here
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public MyClass myclass() {
return new MyClass ();
}
}
複製代碼
你也應該見過這種配置方式:
<bean id="myClass" class="com.demo.MyClass" init-method="init"/>
複製代碼
沒錯,這只是一樣功能的不一樣實現方式罷了 以上就是三種初始化 Spring Beans 的方式,咱們在框架中看到過三種方式在組合使用,那麼組合使用的調用順序是什麼呢?
InitializingBean.afterPropertiesSet()
方法將會被調用瞭解了這些,你也就瞭解了 Spring Bean 是怎麼來的了
經過圖示來講明一下:
組合shying,這個調用順序很難記憶嗎嗎?
PostConstruct
(P)
,afterPropertiesSet(A)
,init-method(I)
--->PAI (圓周率π)
BeanPostProcessor 接口,你們也應該有印象,裏面只有兩個方法:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;
Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}
複製代碼
看方法名,BeforeInitialization 和 AfterInitialization,咱們應該猜得出,這是在上述三種方式的前和後,算是一種全局的切面思想,咱們常常會使用 postProcessAfterInitialization
方法,經過讀取 Bean 的註解完成一些後續邏輯編寫與屬性的設定,如今 Ready for Use
以前是這樣:
在 Ready for Use
以前,瞭解這些內容,已能夠基本知足平常的工做內容,但這並非 Ready for Use 的所有內容,Spring Bean 整個生命週期的流程應該是這樣的,後續文章會逐步點亮:
Ready for Use
以前有用處嗎?XMLBeanFactory
這類方法,包括 XML 配置。這樣作,只不過爲了更清晰的說明問題。歡迎持續關注公衆號:「日拱一兵」,後續會出一系列文章點亮 Spring Bean 週期圖,以完整代碼施力說明這個週期的順序;同時進行 Spring 知識點解釋與串聯,輕鬆搞定面試那點事,以及在工做中充分利用 Spring 的特性