在Spring中,Bean是最基礎的對象,一切操作都是圍繞Bean展開的。Spring是一個BOP(Bean Oriented Programming)框架,Bean在BOP中的作用就像是對象在OOP中的作用一樣。既然如此重要,那麼我們首先需要了解到底什麼是Bean?
什麼是Bean
首先,我們來看看Spring官方文檔對於Bean的定義:
<code>In Spring, the objects that form the backbone of your application and that are managedby
the Spring IoC container are called beans. A beanis
anobject
thatis
instantiated, assembled, and otherwise managedby
a Spring IoC container. Otherwise, a beanis
simply one of many objectsin
your application /<code>
從上面可知,我們可以給Bean下一個定義: Bean就是由IOC實例化、組裝、管理的一個對象 。
Bean的生命週期
我們需要明確的是,在這裡我們的Bean的生命週期主要指的是 singleton bean ,對prototype bean來說,當用戶getBean獲得prototype bean的實例後,IOC容器就不再對當前實例進行管理,而是把管理權交由用戶,此後再getBean生成的是新的實例。對於
request/session/application/websocket 這幾種scope的bean我們在此不談。
在不同的容器中,Bean的生命週期開始的時間不同。對於ApplicationContext來說,當容器啟動的時候,bean就已經實例化了。而對於BeanFactory來說,直到調用 getBean() 方法的時候才進行實例化。
我們知道對於普通的java對象來說,它們的生命週期就是
- 實例化
- 不再使用的時候通過垃圾回收機制進行回收
但是對於Bean來說卻不是這樣。Bean的生命週期如下圖所示
對於如上這些方法,我們可以分成如下幾類
<code>Bean
自身的方法Bean
級生命週期方法 容器級的方法(BeanPostProcessor一系列接口) 工廠後處理器方法(BeanFactoryProcessor
一系列接口) /<code>
Bean自身的方法和Bean級生命週期方法都只對 當前Bean 起作用,但是容器級生命週期方法和工廠後處理器方法是對 所有的bean 都起作用
對於這幾類方法,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該接口有兩個方法:
<code>初始化之前 初始化之後 /<code>
通過方法簽名我們可以知道,我們可以通過beanName來篩選出我們需要進行個性化定製的bean
- InstantiationAwareBeanPostProcessor該類是BeanPostProcessor的子接口,常用的有如下三個方法
<code>實例化之前 實例化之後、設置屬性前 實例化之後 /<code>
測試Bean生命週期
下面我們來編寫一個實例來驗證我們上面所說的Bean生命週期
首先,我們新建一個User,這個Bean實現了我們的BeanNameAware、ApplicationContextAware、InitializingBean、DisposableBean接口
然後我們實現我們自己的BeanPostProcessor
實現自己的
InstantiationAwareBeanPostProcessor
xml配置文件如下
<code><
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
>1value
>constructor-arg
><
constructor-arg
index
="1"
type
="java.lang.String"
><
value
>xiaohuanvalue
>constructor-arg
><
property
name
="id"
value
="2"
/><
property
name
="name"
value
="dahuan"
/>bean
> 複製代碼/<code>
編寫我們自己的測試類
最後運行項目