在Spring中,Bean是最基礎的對象,一切操做都是圍繞Bean展開的。Spring是一個BOP(Bean Oriented Programming)框架,Bean在BOP中的做用就像是對象在OOP中的做用同樣。既然如此重要,那麼咱們首先須要瞭解到底什麼是Bean?java
首先,咱們來看看Spring官方文檔對於Bean的定義:web
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your applicationspring
從上面可知,咱們能夠給Bean下一個定義:Bean就是由IOC實例化、組裝、管理的一個對象
。websocket
咱們須要明確的是,在這裏咱們的Bean的生命週期主要指的是singleton bean
,對prototype bean來講,當用戶getBean得到prototype bean的實例後,IOC容器就再也不對當前實例進行管理,而是把管理權交由用戶,此後再getBean生成的是新的實例。對於request/session/application/websocket 這幾種scope的bean咱們在此不談。session
在不一樣的容器中,Bean的生命週期開始的時間不一樣。對於ApplicationContext來講,當容器啓動的時候,bean就已經實例化了。而對於BeanFactory來講,直到調用getBean()
方法的時候才進行實例化。app
咱們知道對於普通的java對象來講,它們的生命週期就是框架
可是對於Bean來講卻不是這樣。Bean的生命週期以下圖所示socket
對於如上這些方法,咱們能夠分紅以下幾類函數
Bean自身的方法
:好比構造函數、getter/setter以及init-method和destory-method所指定的方法等Bean級生命週期方法
:能夠理解爲Bean類直接實現接口的方法,好比BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean、DisposableBean等方法,這些方法只對當前Bean生效容器級的方法(BeanPostProcessor一系列接口)
:主要是後處理器方法,好比上圖的InstantiationAwareBeanPostProcessor、BeanPostProcessor接口方法。這些接口的實現類是獨立於bean的,而且會註冊到Spring容器中。在Spring容器建立任何Bean的時候,這些後處理器都會發生做用。工廠後處理器方法(BeanFactoryProcessor一系列接口)
:包括AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等。這些都是Spring框架中已經實現好的BeanFactoryPostProcessor,用來實現某些特定的功能。Bean自身的方法和Bean級生命週期方法都只對當前Bean
起做用,可是容器級生命週期方法和工廠後處理器方法是對全部的bean
都起做用post
對於這幾類方法,1 2 4都很好理解,下面咱們重點來講一下什麼是BeanPostProcessor和BeanFactoryPostProcessor
以我我的理解來講,BeanPostProcessor和BeanFactoryPostProcessor就是Spring建立的擴展點
,用戶能夠建立本身的實現類來修改Bean或者BeanFactory
注意對於ApplicatonContext來講,容器能夠自動檢測並加載
BeanPostProcessor和BeanFactoryPostProcessor,可是BeanFactory不行,須要本身調用方法手動註冊
。BeanPostProcessor和BeanFactoryPostProcessor均可以有多個。
ApplicationContext也能夠根據org.springframework.core.PriorityOrdered和org.springframework.core.Ordered來進行自定義排序
,可是BeanFactory不能夠,默認順序就是註冊順序
。
這裏我須要說明下面兩個容易混淆的單詞:
Instantiation
:實例化,指的是調用構造函數
進行實例化Initialization
:初始化,在Bean的聲明週期中指的是init-method
所指定的方法或者是InitializingBean.afterPropertiesSet()
方法下面咱們對經常使用的這些接口進行說明:
BeanNameAware
該接口只有一個方法setBeanName(String name),用來獲取bean的id或者name
BeanFactoryAware
該接口只有一個方法setBeanFactory(BeanFactory beanFactory),用來獲取當前環境中的BeanFactory
ApplicationContextAware
該接口只有一個方法setApplicationContext(ApplicationContext applicationContext),用來獲取當前環境中的ApplicationContext
獲取到IOC容器以後,能夠對beans進行修改等操做
InitializingBean
該接口只有一個方法afterPropertiesSet(),在屬性注入完成後調用
DisposableBean
該接口只有一個方法destroy(),在容器銷燬的時候調用,在用戶指定的destroy-method以前調用
BeanPostProcessor
該接口有兩個方法:
初始化以前
調用此方法初始化以後
調用此方法經過方法簽名咱們能夠知道,咱們能夠經過beanName來篩選出咱們須要進行個性化定製的bean
實例化以前
調用實例化以後、設置屬性前
調用實例化以後
調用下面咱們來編寫一個實例來驗證咱們上面所說的Bean生命週期
首先,咱們新建一個User,這個Bean實現了咱們的BeanNameAware、ApplicationContextAware、InitializingBean、DisposableBean接口
而後咱們實現咱們本身的BeanPostProcessor
實現本身的InstantiationAwareBeanPostProcessor
xml配置文件以下
<context:component-scan base-package="com.xiaohuan.springtest"/>
<bean id="user" class="com.xiaohuan.springtest.beanlifecycle.User" init-method="myInit" destroy-method="myDestroy">
<!-- 構造函數注入 -->
<constructor-arg index="0" type="int">
<value>1</value>
</constructor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>xiaohuan</value>
</constructor-arg>
<!-- setter方法注入 -->
<property name="id" value="2"/>
<property name="name" value="dahuan"/>
</bean>
複製代碼
編寫咱們本身的測試類
最後運行項目