注:Spring Boot Bean的生命周期碎赢,什么是Bean的生命周期,就是Bean從創(chuàng)建到銷(xiāo)毀的過(guò)程辣之。
Bean的生命周期過(guò)程描述
我們先看一下Bean的生命周期過(guò)程中都會(huì)經(jīng)歷些什么僵驰,我先簡(jiǎn)單解釋一下,后面我們通過(guò)源碼進(jìn)行詳細(xì)解釋悍募。首先Spring在實(shí)例化Bean的時(shí)候,會(huì)先調(diào)用它的構(gòu)造函數(shù)洋机,進(jìn)行Bean的實(shí)例化坠宴,然后進(jìn)行Bean的初始化,Bean的初始化經(jīng)過(guò)三個(gè)階段初始化之前(applyBeanPostProcessorsBeforeInitialization)绷旗,其次是進(jìn)行初始化(invokeInitMethods)喜鼓,最后是初始化之后(postProcessAfterInitialization),這就是Bean的初始化過(guò)程衔肢;然后就開(kāi)始利用Bean進(jìn)行業(yè)務(wù)邏輯處理庄岖,最后容器正常關(guān)閉,Spring開(kāi)始銷(xiāo)毀Bean膀懈,Bean的銷(xiāo)毀過(guò)程相對(duì)比較簡(jiǎn)單,調(diào)用DisposableBeanAdapter.destroy()方法谨垃,該方法中有三個(gè)地方比較重要启搂,分別觸發(fā)Bean的生命周期方法,它們是:processor.postProcessBeforeDestruction(this.bean, this.beanName);
((DisposableBean) bean).destroy();
invokeCustomDestroyMethod(this.destroyMethod);
下面我把用圖片來(lái)進(jìn)行直觀(guān)展示:
實(shí)例運(yùn)行
User類(lèi)刘陶,這里就是普通的一個(gè)Bean,用來(lái)添加到容器中胳赌,觀(guān)察其生命周期
package com.itbofeng.bean;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class User implements InitializingBean , DisposableBean {
private String name;
public User() {
System.out.println("調(diào)用Bean的函數(shù)(constructor)");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("調(diào)用Bean的函數(shù)(setName/setAttribute)");
this.name = name;
}
@PostConstruct
public void postConstruct(){
System.out.println("調(diào)用Bean的函數(shù)(postConstruct)");
}
//MainConfig中@Bean 的initMethod
public void initMethod(){
System.out.println("調(diào)用Bean的函數(shù)(initMethod)");
}
//InitializingBean接口的方法afterPropertiesSet
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("調(diào)用Bean的函數(shù)(afterPropertiesSet)");
}
@PreDestroy
public void preDestroy(){
System.out.println("調(diào)用Bean的函數(shù)(preDestroy)");
}
//DisposableBean接口的方法destroy
@Override
public void destroy() throws Exception {
System.out.println("調(diào)用Bean的函數(shù)(destroy)");
}
//MainConfig中@Bean 的destroyMethod
public void destroyMethod(){
System.out.println("調(diào)用Bean的函數(shù)(destroyMethod)");
}
}
CustomBeanPostProcessor類(lèi),用來(lái)觀(guān)察BeanPostProcessor的運(yùn)行時(shí)期
package com.itbofeng.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Nullable
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean.getClass()==User.class){
System.out.println("調(diào)用postProcessBeforeInitialization...");
}
return bean;
}
@Nullable
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean.getClass()==User.class){
System.out.println("調(diào)用postProcessAfterInitialization...");
}
return bean;
}
}
MainConfig類(lèi)匙隔,SpringBoot程序運(yùn)行的主類(lèi)疑苫,并將User和CustomBeanPostProcessor 加入到容器中
package com.itbofeng;
import com.itbofeng.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class MainConfig {
public static void main(String[] args) {
SpringApplication.run(MainConfig.class,args);
}
@Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
public User user(){
return new User();
}
}
運(yùn)行結(jié)果查看
源碼解析
初始化過(guò)程
首先我們將斷點(diǎn)打到CustomBeanPostProcessor.postProcessBeforeInitialization的第一行代碼,然后我看一下其方法調(diào)用棧:
主要包括兩個(gè)地方,一個(gè)是容器刷新捍掺,第二個(gè)是初始化Bean撼短,我們先對(duì)這容器刷新的源碼進(jìn)行簡(jiǎn)單查看
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
注意finishBeanFactoryInitialization,上面說(shuō)明也解釋說(shuō)該方法的作用是初始化所有剩下的非懶加載的單例Bean,從該描述也可以知道挺勿,懶加載和原型的Bean在該階段并不會(huì)被加載曲横,這部分代碼是Spring容器刷新時(shí)的代碼,也是Spring IOC比較核心的代碼不瓶,在學(xué)習(xí)后面中禾嫉,慢慢將該部分的代碼慢慢學(xué)習(xí),接下來(lái)我們看一下初始化Bean部分的代碼:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//對(duì)實(shí)現(xiàn)了Aware接口的方法進(jìn)行執(zhí)行蚊丐,方法就在下方熙参,使用方法直接實(shí)現(xiàn)對(duì)應(yīng)的Aware接口即可
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//執(zhí)行實(shí)現(xiàn)了BeanPostProcessor的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//執(zhí)行初始化方法
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()) {
//執(zhí)行實(shí)現(xiàn)了BeanPostProcessor的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
//調(diào)用InitializingBean的afterPropertiesSet方法
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
//調(diào)用@Bean制定的的initMethod方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
以上就是初始化階段,我們會(huì)發(fā)現(xiàn)初始化過(guò)程中沒(méi)有@PostConstruct注解標(biāo)注的方法麦备,那是因?yàn)閷?duì)@PostConstruct的處理也是BeanPostProcessor的實(shí)現(xiàn)類(lèi)InitDestroyAnnotationBeanPostProcessor孽椰,那么我們就應(yīng)該有疑問(wèn)為什么InitDestroyAnnotationBeanPostProcessor.postProcessBeforeDestruction為什么會(huì)在CustomBeanPostProcessor.postProcessBeforeInitialization之后進(jìn)行,是因?yàn)槿绻恢付樞蚰J(rèn)我們的getOrder為0泥兰,而InitDestroyAnnotationBeanPostProcessor的getOrder為Ordered.LOWEST_PRECEDENCE=2147483647,getOrder越大則弄屡,優(yōu)先級(jí)越低,所以我們自定義的在其之前鞋诗,至此初始化部分結(jié)束膀捷。
下面我們簡(jiǎn)單看一下銷(xiāo)毀階段:
public void destroy() {
//處理@PreDestroy注解注釋的方法
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
//處理實(shí)現(xiàn)了DisposableBean接口的destroy的方法
if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) bean).destroy();
return null;
}, acc);
}
else {
((DisposableBean) bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
//處理@Bean指定的destroyMethod方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod(this.destroyMethodName);
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
結(jié)束語(yǔ)
至此,我們Bean的生命周期探索初步結(jié)束削彬,后面再做進(jìn)一步深入學(xué)習(xí)全庸,在學(xué)習(xí)本節(jié)課時(shí)要多進(jìn)行調(diào)試,斷點(diǎn)跟蹤融痛,會(huì)更加有效果壶笼。另外無(wú)論是在初始化還是在結(jié)束時(shí)都是處理的單例的Bean,而且在初始化時(shí),處理的Bean還是非懶加載的雁刷,所以需要特殊說(shuō)明:非懶加載的單實(shí)例Bean的生命周期如上;懶加載的單實(shí)例Bean是在第一次獲取進(jìn)行初始化過(guò)程;原型Bean是在每次獲取時(shí)都進(jìn)行初始化覆劈,而且Spring容器不會(huì)管理器銷(xiāo)毀。
最近在網(wǎng)上看到了一篇文章沛励,很不錯(cuò)责语,詳細(xì)的介紹了Spring IOC的原理,如果大家想詳細(xì)了解Spring的IOC可以看一下:https://www.cnblogs.com/ITtangtang/p/3978349.html目派,好東西大家一起分享坤候,????????????????????????????????