除了使用階段外,Spring 將 bean 的生命週期定義爲實例化、屬性填充、初始化和銷燬四個階段,併爲每一個階段提供了多個拓展點用於自定義 bean 的建立過程。這篇文章介紹了 bean 的生命週期和其各個拓展點,經過圖示生動的展現、並結合一個實例來演示全過程。java
上圖中,每一個箭頭上都有 Spring 提供的拓展點。類加載不是 bean 生命週期的一部分,保留在圖上純粹是由於要提供第一個右向的箭頭,而使用階段也不在討論範圍內,故這兩個採用圓角矩形。web
Spring 提供的拓展點能夠分爲:spring
用於單個 bean 感知自身過程的專用拓展點:下方出現的、以 Aware 結尾爲名的接口,org.springframework.beans.factory.InitializingBean
接口和 org.springframework.beans.factory.DisposableBean
接口,這些接口都只定義了一個函數。bean 經過實現這些接口、重寫其中的函數來實現拓展點。Spring 容器會在適當的時候調用這些函數。app
用於全部普通 bean 初始化的通用拓展點:位於 org.springframework.beans.factory.config
包的 BeanPostProcessor
、InstantiationAwareBeanPostProcessor
和 DestructionAwareBeanPostProcessor
接口,這些接口中定義了多個拓展點,使用時須要定義一個專門的類實現接口、重寫必要的函數。Spring 容器會將這些實現類優先註冊爲 bean,待它們初始化完成後再初始化普通的 bean,在每一個普通 bean 註冊時,Spring 容器都會嘗試調用全部已註冊的通用拓展點。ide
建立 bean 對象實例的過程,包括使用工廠模式建立和調用構造函數。Spring 經過 InstantiationAwareBeanPostProcessor
接口在實例化前和後各提供了兩個通用拓展點,加上對象實例化的過程,執行順序以下:函數
postProcessBeforeInstantiation
:在普通 bean 對象實例化開始以前調用postProcessAfterInstantiation
:在普通 bean 對象實例化完成以後調用若是對象中有 setter 函數,並經過配置元數據指定了注入的屬性,Spring 容器會在這一步爲其注入配置的值。完成屬性填充後,Spring 經過 Aware(意爲感知) 接口提供了十個專用拓展點,這些拓展點用於在 bean 自身內部、感知一些外部信息使用。調用順序以下(下面提到的多個 Aware 接口中,前三個在 org.springframework.beans.factory
包中,4 ~ 9 在 org.springframework.context
包中,最後一個在 org.springframework.web.context
包中 ):post
BeanNameAware#setBeanName
BeanClassLoaderAware#setBeanClassLoader
BeanFactoryAware#setBeanFactory
EnvironmentAware#setEnvironment
EmbeddedValueResolverAware#setEmbeddedValueResolver
ResourceLoaderAware#setResourceLoader
(僅在 ApplicationContext 中有效)ApplicationEventPublisherAware#setApplicationEventPublisher
(僅在 ApplicationContext 中有效)MessageSourceAware#setMessageSource
(僅在 ApplicationContext 中有效)ApplicationContextAware#setApplicationContext
(僅在 ApplicationContext 中有效)ServletContextAware#setServletContext
(僅在 WebApplicationContext 中有效)Aware 拓展點結束以後,還有一個用於在初始化以前、進行屬性校驗的 InitializingBean#afterPropertiesSet
專用拓展點。this
初始化是指經過 bean 在將要工做前進行的最後準備工做,一般是 @Bean
的initMethod
屬性定義的函數執行的過程 。Spring 經過 BeanPostProcessor
接口在初始化以前和以後提供了兩個通用拓展點,加上初始化函數執行順序爲:日誌
postProcessBeforeInitialization
postProcessAfterInitialization
銷燬是指 bean 釋放其佔用的一些外部資源的過程,一般是 @Bean
註解的 destroyMethod
屬性定義的銷燬函數執行的過程。Spring 經過 DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
的通用拓展點,再加上 DisposableBean#destroy
提供了的專用拓展點,三者執行順序爲:code
DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
DisposableBean#destroy
一個簡單的演示,實現了上文提到的 bean 生命週期所有的拓展點,經過日誌打印的方式觀察執行順序來直觀的感覺。
SimpleBean 類
/** * 一個簡單的 bean 實例,實現了 Spring 提供的 bean 生命週期全拓展點,內部函數實現順序即爲 bean 生命週期中各個函數的調用順序 */ @Slf4j(topic = "簡單Bean") public class SimpleBean implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware, InitializingBean, DisposableBean { private EmptyBean emptyBean; static { //類加載期間 logger 尚未初始化,使用標準輸出 System.out.printf("[%s] 簡單Bean : SimpleBean 類加載 loaded%n", Thread.currentThread().getName()); } public SimpleBean() { log.info("構造函數執行,建立實例"); } @Autowired public void setEmptyBean(EmptyBean emptyBean) { this.emptyBean = emptyBean; log.info("setter 函數執行,裝配了 {}", this.emptyBean); } /** 用於通知 bean 感知自身名稱 */ @Override public void setBeanName(String name) { log.info("bean 名稱爲 {}", name); } /** 用於通知 bean 感知加載自身的類加載器 */ @Override public void setBeanClassLoader(ClassLoader classLoader) { log.info("類加載器是 {}", classLoader); } /** 用於通知 bean 感知建立自身的 bean 工廠 */ @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { //BeanFactory 可能會重寫 toString(),形成日誌輸出過多不便於查閱 log.info("由 {}@{} 建立", beanFactory.getClass(), beanFactory.hashCode()); } /** 設置該 bean 的運行環境信息 */ @Override public void setEnvironment(Environment environment) { //environment.toString() 會將全部環境信息輸出,形成日誌輸出過多不便於查閱 log.info("運行的 JVM 型號是 {}", environment.getProperty("java.vm.name")); } /** 設置嵌入式配置解析器,可用於解析嵌入在應用程序包內的配置文件中的文本值 */ @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { //在 application.properties 中定義了 editor.name 信息 log.info("做者是 {}", resolver.resolveStringValue("${editor.name}")); } /** 設置用於資源解析的解析器,可用於解析任意格式的資源 */ @Override public void setResourceLoader(ResourceLoader resourceLoader) { log.info("資源解析器對象:{}", resourceLoader); } /** 設置事件發佈器,與 Spring 提供的事件發佈訂閱機制有關 */ @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { log.info("事件發佈器對象:{}", applicationEventPublisher); } /** 設置消息原,可用於實現國際化 */ @Override public void setMessageSource(MessageSource messageSource) { log.info("消息源對象:{}", messageSource); } /** 爲當前 bean 傳入 ApplicationContext 引用,可以使用該容器引用獲取其餘 bean 的引用 */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.info("應用程序上下文對象:{}", applicationContext.getDisplayName()); } /** 在全部屬性設置和 Aware 接口定義的行爲都執行完成後,由 BeanFactory 調用,bean 可在此校驗自身配置並最終初始化 */ @Override public void afterPropertiesSet() { log.info("屬性裝配所有完成,校驗無誤,開始初始化"); } /** 自定義的初始化方法 */ public void initMethod() { log.info("自定義的初始化方法"); } /** 容器銷燬時調用 */ @Override public void destroy() { log.info("容器即將關閉,銷燬其中的 bean"); } /** 自定義的銷燬方法 */ public void destroyMethod() { log.info("自定義的銷燬方法"); } }
/** 一個空的 bean,用於在 SimpleBean 中進行 setter 注入 */ @Component public class EmptyBean { }
@Slf4j(topic = "自定義實例化處理器") @Component public class CustomInstantiationProcessor implements InstantiationAwareBeanPostProcessor { public CustomInstantiationProcessor() { log.info("InstantiationAwareBeanPostProcessor 在其餘 bean 建立前就建立完成"); } /** 其餘 bean 實例化以前調用 */ @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if (beanClass.equals(SimpleBean.class)) { log.info("{} 即將實例化", beanName); } return null; } /** 其餘 bean 實例化以後調用 */ @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if (bean instanceof SimpleBean) { log.info("{} 實例化完成", beanName); } return true; } }
@Slf4j(topic = "自定義初始化處理器") @Component public class CustomInitializationProcessor implements BeanPostProcessor { public CustomInitializationProcessor() { log.info("BeanPostProcessor 在其餘 bean 建立前就建立完成"); } /** 其餘 bean 初始化以前調用 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof SimpleBean) { log.info("{} 即將初始化", beanName); } return bean; } /** 其餘 bean 初始化完成以後調用 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof SimpleBean) { log.info("{} 初始化完成", beanName); } return bean; } }
@Slf4j(topic = "自定義銷燬處理器") @Component public class CustomDestructionProcessor implements DestructionAwareBeanPostProcessor { public CustomDestructionProcessor() { log.info("DestructionAwareBeanPostProcessor 在其餘 bean 建立前就建立完成"); } /** 其餘 bean 銷燬以前調用 */ @Override public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException { if (bean instanceof SimpleBean) { log.info("{} 即將銷燬", beanName); } } }
@Slf4j @SpringBootApplication public class DemoApplication implements CommandLineRunner { private SimpleBean bean; @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod") public SimpleBean simpleBean() { return new SimpleBean(); } @Autowired public void setBean(SimpleBean bean) { this.bean = bean; } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Override public void run(String... args) { log.info("{} 使用", bean.toString()); } }
InitializingBean#afterPropertiesSet
,拓展點以前執行,後續查閱源碼研究。