既然你們都放這個圖,那我也放吧:java
Bean 的生命週期歸納起來就是 4 個階段:web
看什麼都沒有直接看源代碼清楚,來吧,上代碼:spring
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.7</version> </dependency>
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { //1-實例化 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = this.createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } synchronized(mbd.postProcessingLock) { if (!mbd.postProcessed) { try { this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable var17) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17); } mbd.postProcessed = true; } } boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName); if (earlySingletonExposure) { if (this.logger.isTraceEnabled()) { this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } this.addSingletonFactory(beanName, () -> { return this.getEarlyBeanReference(beanName, mbd, bean); }); } Object exposedObject = bean; try { //2-屬性賦值 this.populateBean(beanName, mbd, instanceWrapper); //3-初始化 exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) { throw (BeanCreationException)var18; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18); } if (earlySingletonExposure) { Object earlySingletonReference = this.getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) { String[] dependentBeans = this.getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length); String[] var12 = dependentBeans; int var13 = dependentBeans.length; for(int var14 = 0; var14 < var13; ++var14) { String dependentBean = var12[var14]; if (!this.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."); } } } } //4-銷燬-註冊回調接口 try { this.registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject; } catch (BeanDefinitionValidationException var16) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16); } }
因爲初始化包含了第 3~7步,較複雜,因此咱們進到 initializeBean() 方法裏具體看下其過程(註釋的序號對應圖中序號):mvc
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { //3-檢查 Aware 相關接口並設置相關依賴 if (System.getSecurityManager() != null) { AccessController.doPrivileged(() -> { //Aware系列接口,主要用於輔助Spring bean訪問Spring容器 this.invokeAwareMethods(beanName, bean); return null; }, this.getAccessControlContext()); } else { this.invokeAwareMethods(beanName, bean); } // 4-BeanPostProcessor 前置處理 Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName); } // 5-若實現 InitializingBean 接口,調用 afterPropertiesSet() 方法,這倆個方法都在invokeInitMethods裏面 // 6-若配置自定義的 init-method方法,則執行 try { this.invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable var6) { throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6); } // 7-BeanPostProceesor 後置處理 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
銷燬的過程app
public void destroy() { if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { Iterator var1 = this.beanPostProcessors.iterator(); while(var1.hasNext()) { DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next(); processor.postProcessBeforeDestruction(this.bean, this.beanName); } } //// 9-若實現 DisposableBean 接口,則執行 destory()方法 if (this.invokeDisposableBean) { if (logger.isTraceEnabled()) { logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'"); } try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(() -> { ((DisposableBean)this.bean).destroy(); return null; }, this.acc); } else { ((DisposableBean)this.bean).destroy(); } } catch (Throwable var3) { String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'"; if (logger.isDebugEnabled()) { logger.warn(msg, var3); } else { logger.warn(msg + ": " + var3); } } } // 10-若配置自定義的 detory-method 方法,則執行 if (this.destroyMethod != null) { this.invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName); if (methodToInvoke != null) { this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); } } }
在 bean 初始化時會經歷幾個階段,首先可使用註解 @PostConstruct
, @PreDestroy
來在 bean 的建立和銷燬階段進行調用:ide
@Component public class AnnotationBean { private final static Logger LOGGER = LoggerFactory.getLogger(AnnotationBean.class); @PostConstruct public void start(){ LOGGER.info("AnnotationBean start"); } @PreDestroy public void destroy(){ LOGGER.info("AnnotationBean destroy"); } }
還能夠實現 InitializingBean,DisposableBean
這兩個接口,也是在初始化以及銷燬階段調用:post
@Service public class SpringLifeCycleService implements InitializingBean,DisposableBean{ private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleService.class); @Override public void afterPropertiesSet() throws Exception { LOGGER.info("SpringLifeCycleService start"); } @Override public void destroy() throws Exception { LOGGER.info("SpringLifeCycleService destroy"); } }
也能夠自定義方法用於在初始化、銷燬階段調用:this
@Configuration public class LifeCycleConfig { @Bean(initMethod = "start", destroyMethod = "destroy") public SpringLifeCycle create(){ SpringLifeCycle springLifeCycle = new SpringLifeCycle() ; return springLifeCycle ; } } public class SpringLifeCycle{ private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycle.class); public void start(){ LOGGER.info("SpringLifeCycle start"); } public void destroy(){ LOGGER.info("SpringLifeCycle destroy"); } }
以上是在 SpringBoot 中能夠這樣配置,若是是原始的基於 XML 也是可使用:代理
<bean class="com.crossoverjie.spring.SpringLifeCycle" init-method="start" destroy-method="destroy"> </bean>
若 Spring 檢測到 bean 實現了 Aware 接口,則會爲其注入相應的依賴。因此經過讓bean 實現 Aware 接口,則能在 bean 中得到相應的 Spring 容器資源。rest
Spring 中提供的 Aware 接口有:
其代碼實現以下:
// AbstractAutowireCapableBeanFactory.java private void invokeAwareMethods(String beanName, Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware)bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = this.getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware)bean).setBeanFactory(this); } } }
以上是針對 BeanFactory 類型的容器,而對於 ApplicationContext 類型的容器,也提供了 Aware 接口,只不過這些 Aware 接口的注入實現,是經過 BeanPostProcessor 的方式注入的,但其做用還是注入依賴。
其代碼實現以下:
// ApplicationContextAwareProcessor.java private void invokeAwareInterfaces(Object bean) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware)bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext); } }
實現 Aware 接口
例子:
@Component public class SpringLifeCycleAware implements ApplicationContextAware { private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleAware.class); private ApplicationContext applicationContext ; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext ; LOGGER.info("SpringLifeCycleAware start"); } }
實現 BeanPostProcessor 接口,Spring 中全部 bean 在作初始化時都會調用該接口中的兩個方法,能夠用於對一些特殊的 bean 進行處理:
public interface BeanPostProcessor { // 初始化前置處理 default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } // 初始化後置處理 default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
經常使用場景有:
例如 Spring AOP 功能,生成對象的代理類,而後返回。
// AbstractAutoProxyCreator.java public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); // 返回代理類 return proxy; } return null; }
例子:
@Component public class SpringLifeCycleProcessor implements BeanPostProcessor { private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleProcessor.class); /** * 預初始化 初始化以前調用 * @param bean * @param beanName * @return * @throws BeansException */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("annotationBean".equals(beanName)){ LOGGER.info("SpringLifeCycleProcessor start beanName={}",beanName); } return bean; } /** * 後初始化 bean 初始化完成調用 * @param bean * @param beanName * @return * @throws BeansException */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("annotationBean".equals(beanName)){ LOGGER.info("SpringLifeCycleProcessor end beanName={}",beanName); } return bean; } } //結果 結果: 00:40:24.856 [restartedMain] INFO c.c.s.p.SpringLifeCycleProcessor - SpringLifeCycleProcessor start beanName=annotationBean 結果: 00:40:24.860 [restartedMain] INFO c.c.spring.annotation.AnnotationBean - AnnotationBean start 結果: 00:40:24.861 [restartedMain] INFO c.c.s.p.SpringLifeCycleProcessor - SpringLifeCycleProcessor end beanName=annotationBean 結果: 00:40:24.864 [restartedMain] INFO c.c.s.aware.SpringLifeCycleAware - SpringLifeCycleAware start 結果: 00:40:24.867 [restartedMain] INFO c.c.s.service.SpringLifeCycleService - SpringLifeCycleService start 結果: 00:40:24.887 [restartedMain] INFO c.c.spring.SpringLifeCycle - SpringLifeCycle start 結果: 00:40:25.062 [restartedMain] INFO o.s.b.d.a.OptionalLiveReloadServer - LiveReload server is running on port 35729 結果: 00:40:25.122 [restartedMain] INFO o.s.j.e.a.AnnotationMBeanExporter - Registering beans for JMX exposure on startup 結果: 00:40:25.140 [restartedMain] INFO com.crossoverjie.Application - Started Application in 2.309 seconds (JVM running for 3.681) 結果: 00:40:25.143 [restartedMain] INFO com.crossoverjie.Application - start ok! 結果: 00:40:25.153 [Thread-8] INFO o.s.c.a.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3913adad: startup date [Wed Mar 21 00:40:23 CST 2018]; root of context hierarchy 結果: 00:40:25.155 [Thread-8] INFO o.s.j.e.a.AnnotationMBeanExporter - Unregistering JMX-exposed beans on shutdown 結果: 00:40:25.156 [Thread-8] INFO c.c.spring.SpringLifeCycle - SpringLifeCycle destroy 結果: 00:40:25.156 [Thread-8] INFO c.c.s.service.SpringLifeCycleService - SpringLifeCycleService destroy 結果: 00:40:25.156 [Thread-8] INFO c.c.spring.annotation.AnnotationBean - AnnotationBean destroy
直到 Spring 上下文銷燬時則會調用自定義的銷燬方法以及實現了 DisposableBean
的 destroy()
方法。
InitializingBean 和 init-method 是 Spring 爲 bean 初始化提供的擴展點。
InitializingBean接口 的定義以下:
public interface InitializingBean { void afterPropertiesSet() throws Exception; }
在 afterPropertiesSet() 方法寫初始化邏輯。
指定 init-method 方法,指定初始化方法:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="demo" class="com.chaycao.Demo" init-method="init()"/> </beans>
DisposableBean 和 destory-method 與上述相似,就不描述了。
最後總結下如何記憶 Spring Bean 的生命週期:
詳情請見: