1.概述
首先Bean就是一些JAVA對象,只不過這些Bean不是我們主動new出來的,而是交個Spring IOC容器創建并管理的,因此Bean的生命周期受Spring IOC容器控制,Bean生命周期大致分為以下幾個階段:
-
Bean的實例化(Instantiation):Spring框架會取出BeanDefinition的信息進行判斷當前Bean的范圍是否是singleton的,是否不是延遲加載的,是否不是FactoryBean等,最終將一個普通的singleton的Bean通過反射進行實例化
-
Bean的屬性賦值(Populate):Bean實例化之后還僅僅是個"半成品",還需要對Bean實例的屬性進行填充,Bean的屬性賦值就是指 Spring 容器根據BeanDefinition中屬性配置的屬性值注入到 Bean 對象中的過程。
-
Bean的初始化(Initialization):對Bean實例的屬性進行填充完之后還需要執行一些Aware接口方法、執行BeanPostProcessor方法、執行InitializingBean接口的初始化方法、執行自定義初始化init方法等。該階段是Spring最具技術含量和復雜度的階段,并且Spring高頻面試題Bean的循環引用問題也是在這個階段體現的;
-
Bean的使用階段:經過初始化階段,Bean就成為了一個完整的Spring Bean,被存儲到單例池singletonObjects中去了,即完成了Spring Bean的整個生命周期,接下來Bean就可以被隨心所欲地使用了。
-
Bean的銷毀(Destruction):Bean 的銷毀是指 Spring 容器在關閉時,執行一些清理操作的過程。在 Spring 容器中, Bean 的銷毀方式有兩種:銷毀方法destroy-method和 DisposableBean 接口。
2.Bean生命周期詳解和使用案例
BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor,BeanPostProcessor這三個后置處理器的調用時機都在Spring Bean生命周期中是不嚴謹的,按照上面我們對Bean生命周期的階段劃分,只有BeanPostProcessor作用于Bean的生命周期中,而BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor是針對BeanDefinition的,所以不屬于Bean的生命周期中。
BeanPostProcessor在Bean生命周期的體現如下圖所示:
Bean的生命周期和人的一生一樣都會經歷從出生到死亡,中間是一個漫長且復雜的過程,接下來我們就來整體分析一下Bean生命周期的核心流程和相關接口回調方法的調用時機,同時這里想強調一下Bean的生命周期也是面試的高頻考點,對核心流程務必要掌握清楚,這里用一張流程圖進行詳述展示,是重點、重點、重點。
根據上面的Bean生命周期核心流程做如下代碼演示示例:
Bean定義:
@Data
@AllArgsConstructor
public class Boo implements InitializingBean, DisposableBean, BeanNameAware {
private Long id;
private String name;
public Boo() {
System.out.println("boo實例化構造方法執行了...");
}
@PostConstruct
public void initMethod() {
System.out.println("boo執行初始化init()方法了...");
}
@PreDestroy
public void destroyMethod() {
System.out.println("boo執行初始化destroy()方法了...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("boo執行InitializingBean的afterPropertiesSet()方法了...");
}
@Override
public void destroy() throws Exception {
System.out.println("boo執行DisposableBean的destroy()方法了...");
}
@Override
public void setBeanName(String name) {
System.out.println("boo執行BeanNameAware的setBeanName()方法了...");
}
}
實現InstantiationAwareBeanPostProcessor:
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> BeanClass, String BeanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor的before()執行了...." + BeanName);
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object Bean, String BeanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor的after()執行了...." + BeanName);
return false;
}
}
實現BeanPostProcessor:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object Bean, String BeanName) throws BeansException {
System.out.println("BeanPostProcessor的before()執行了...." + BeanName);
return Bean;
}
@Override
public Object postProcessAfterInitialization(Object Bean, String BeanName) throws BeansException {
System.out.println("BeanPostProcessor的after()執行了...."+ BeanName);
return Bean;
}
}
執行下面的配置類測試方法:
@ComponentScan(basePackages = {"com.shepherd.common.config"})
@Configuration
public class MyConfig {
@Bean
public Boo boo() {
return new Boo();
}
public static void mAIn(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
String[] BeanDefinitionNames = applicationContext.getBeanDefinitionNames();
// 遍歷Spring容器中的BeanName
for (String BeanDefinitionName : BeanDefinitionNames) {
System.out.println(BeanDefinitionName);
}
// 這里調用的applicationContext的close()觸發Bean的銷毀回調方法
applicationContext.close();
}
}
名為boo的Bean相關運行結果如下:
InstantiationAwareBeanPostProcessor的before()執行了....boo
boo實例化構造方法執行了...
InstantiationAwareBeanPostProcessor的after()執行了....boo
boo執行BeanNameAware的setBeanName()方法了...
BeanPostProcessor的before()執行了....boo
boo執行初始化init()方法了...
boo執行InitializingBean的afterPropertiesSet()方法了...
BeanPostProcessor的after()執行了....boo
......
boo執行初始化destroy()方法了...
boo執行DisposableBean的destroy()方法了...
根據控制臺打印結果可以boo的相關方法執行順序嚴格遵從上面流程圖,同時當我們執行容器applicationContext的關閉方法close()會觸發調用bean的銷毀回調方法。
3.淺析Bean生命周期源碼實現
DefaultListableBeanFactory是Spring IOC的Bean工廠的一個默認實現,IOC大部分核心邏輯實現都在這里,可關注。Bean生命周期就是創建Bean的過程,這里我們就不在拐彎抹角兜圈子,直接來到DefaultListableBeanFactory繼承的AbstractAutowireCapableBeanFactory的#doCreateBean()方法,之前說過在Spring框架中以do開頭的方法都是核心邏輯實現所在
protected Object doCreateBean(String BeanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the Bean.
// BeanWrapper 是對 Bean 的包裝,其接口中所定義的功能很簡單包括設置獲取被包裝的對象,獲取被包裝 Bean 的屬性描述器
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// <1> 單例模型,則從未完成的 FactoryBean 緩存中刪除
instanceWrapper = this.factoryBeanInstanceCache.remove(BeanName);
}
if (instanceWrapper == null) {
// <2> 使用合適的實例化策略來創建新的實例:工廠方法、構造函數自動注入、簡單初始化
instanceWrapper = createBeanInstance(BeanName, mbd, args);
}
// 包裝的實例對象
Object Bean = instanceWrapper.getWrappedInstance();
// 包裝的實例class類型
Class<?> BeanType = instanceWrapper.getWrappedClass();
if (BeanType != NullBean.class) {
mbd.resolvedTargetType = BeanType;
}
// Allow post-processors to modify the merged Bean definition.
// <3> 判斷是否有后置處理
// 如果有后置處理,則允許后置處理修改 BeanDefinition
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, BeanType, BeanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), BeanName,
"Post-processing of merged Bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// <4> 解決單例模式的循環依賴
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(BeanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching Bean '" + BeanName +
"' to allow for resolving potential circular references");
}
// 提前將創建的 Bean 實例加入到 singletonFactories 中
// 這里是為了后期避免循環依賴
addSingletonFactory(BeanName, () -> getEarlyBeanReference(BeanName, mbd, Bean));
}
// Initialize the Bean instance.
// 開始初始化 Bean 實例對象
Object exposedObject = Bean;
try {
// <5> 對 Bean 進行填充,將各個屬性值注入,其中,可能存在依賴于其他 Bean 的屬性
// 則會遞歸初始依賴 Bean
populateBean(BeanName, mbd, instanceWrapper);
// <6> 調用初始化方法
exposedObject = initializeBean(BeanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && BeanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), BeanName, "Initialization of Bean failed", ex);
}
}
// <7> 循環依賴處理
if (earlySingletonExposure) {
// 獲取 earlySingletonReference
Object earlySingletonReference = getSingleton(BeanName, false);
// 只有在存在循環依賴的情況下,earlySingletonReference 才不會為空
if (earlySingletonReference != null) {
// 如果 exposedObject 沒有在初始化方法中被改變,也就是沒有被增強
if (exposedObject == Bean) {
exposedObject = earlySingletonReference;
}
// 處理依賴
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(BeanName)) {
String[] dependentBeans = getDependentBeans(BeanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(BeanName,
"Bean with name '" + BeanName + "' has been injected into other Beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other Beans do not use the final version of the " +
"Bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register Bean as disposable.
try {
// <8> 注冊 Bean的銷毀邏輯
registerDisposableBeanIfNecessary(BeanName, Bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), BeanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
由上面代碼可知,Bean的創建過程核心步驟如下:
-
createBeanInstance(BeanName, mbd, args) 進行Bean的實例化 -
populateBean(BeanName, mbd, instanceWrapper)進行Bean的屬性填充賦值 -
initializeBean(BeanName, exposedObject, mbd)處理Bean初始化之后的各種回調事件 -
registerDisposableBeanIfNecessary(BeanName, Bean, mbd)注冊Bean的銷毀接口 -
解決創建Bean過程中的循環依賴,Spring使用三級緩存解決循環依賴,這也是一個重要的知識點,這里不詳細闡述,后面會安排
接下來我們就來看看和Bean初始化階段相關各種回調事件執行方法#initializeBean(),分析一下上面流程圖的執行順序是怎么實現的。
protected Object initializeBean(final String BeanName, final Object Bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(BeanName, Bean);
return null;
}
}, getAccessControlContext());
}
else {
// 涉及到的回調接口點進去一目了然,代碼都是自解釋的
// BeanNameAware、BeanClassLoaderAware或BeanFactoryAware
invokeAwareMethods(BeanName, Bean);
}
Object wrappedBean = Bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回調
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, BeanName);
}
try {
// init-methods
// 或者是實現了InitializingBean接口,會調用afterPropertiesSet() 方法
invokeInitMethods(BeanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
BeanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessAfterInitialization 回調
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, BeanName);
}
return wrappedBean;
}
至于Bean的銷毀流程與Bean初始化類似,從上面的使用示例中看可以得出當容器關閉時,才會對Bean銷毀方法進行調用。銷毀過程是這樣的。順著close()-> doClose() -> destroyBeans() -> destroySingletons() -> destroySingleton() -> destroyBean() -> Bean.destroy() ,會看到最終調用Bean的銷毀方法。這里就不在展示源碼細節啦,有興趣的話自行去調試查看了解
4.總結
以上全部就是對Spring Bean生命周期的全面總結, Spring 的 Bean 容器機制是非常強大的,它可以幫助我們輕松地管理 Bean 對象,并且提供了豐富的生命周期回調方法,允許我們在 Bean 的生命周期中執行自己的特定操作,這對于我們平時工作使用中進行增強擴展至關重要,因此掌握Bean的生命周期是必須的。






