1.可擴充的接口啟動調用順序圖
org.springframework.beans.factory.xxx
org.springframework.boot.xxx
org.springframework.context.xxx

- ApplicationContextInitializer.initialize
- AbstractApplicationContext.refresh
- BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry
- BeanDefinitionRegistryPostProcessor.postProcessBeanFactory
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
- SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors
- MergedBeanDefinitionPostProcessor.postProcessorMergedBeanDefinition
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
- SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
- BeanFactoryAware.setBeanFactory
- InstantiationAwareBeanPostProcessor.postProcessPropertyValues
- ApplicationContextAwareProcessor.invokeAwareInterfaces
- BeanNameAware.setBeanName
- InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization
- @PostConstruct
- InitiallzingBean.afterPropertiesSet
- InstantiationAwareBeanPostProcessor.postProcessAfterInitialization
- FactoryBean.getObject
- SmartInitilallzingSingleton.afterSingletonInstantiated
- CommondLineRunner.run
- DisposableBean.destry
2.ApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer
這是整個spring容器在重新整理之前初始化
ConfigurableApplicationContext
的回調接口,簡單來說,就是在容器重新整理之前調用此類的initialize方法。這個點允許被使用者自己擴充。使用者可以在整個spring容器還沒被初始化之前做一些事情。
可以想到的場景可能為,在最開始
激活一些配置
,或者利用這時候class還沒被類加載器加載的時機,進行
動态位元組碼注入
等操作。
public class TestApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("[ApplicationContextInitializer]");
}
}
因為這時候spring容器還沒被初始化,是以想要自己的擴充的生效,有以下三種方式:
- 在啟動類中用
語句加入springApplication.addInitializers(new TestApplicationContextInitializer())
- 配置檔案配置
context.initializer.classes=com.example.demo.TestApplicationContextInitializer
- Spring SPI擴充,在spring.factories中加入
org.springframework.context.ApplicationContextInitializer=com.example.demo.TestApplicationContextInitializer
3.BeanDefinitionRegistryPostProcessor
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
這個接口在讀取項目中的beanDefinition之後執行,提供一個補充的擴充點
使用場景:你可以在這裡動态注冊自己的beanDefinition,可以加載classpath之外的bean
public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("[BeanDefinitionRegistryPostProcessor] postProcessBeanDefinitionRegistry");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("[BeanDefinitionRegistryPostProcessor] postProcessBeanFactory");
}
}
4.BeanFactoryPostProcessor
org.springframework.beans.factory.config.BeanFactoryPostProcessor
org.springframework.beans.factory.config.BeanFactoryPostProcessor
這個接口是beanFactory的擴充接口,調用時機在spring在讀取beanDefinition資訊之後,執行個體化bean之前。
在這個時機,使用者可以通過實作這個擴充接口來自行處理一些東西,比如
修改已經注冊的beanDefinition的元資訊
。
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("[BeanFactoryPostProcessor]");
}
}
5.InstantiationAwareBeanPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
繼承了
BeanPostProcessor
, 而
BeanPostProcessor
隻在bean的初始化階段進行擴充, 而
InstantiationAwareBeanPostProcessor
接口則在初始化階段, 執行個體化階段和屬性注入階段
public class TestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[TestInstantiationAwareBeanPostProcessor] before initialization " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[TestInstantiationAwareBeanPostProcessor] after initialization " + beanName);
return bean;
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("[TestInstantiationAwareBeanPostProcessor] before instantiation " + beanName);
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("[TestInstantiationAwareBeanPostProcessor] after instantiation " + beanName);
return true;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("[TestInstantiationAwareBeanPostProcessor] postProcessPropertyValues " + beanName);
return pvs;
}
- postProcessBeforeInstantiation: 執行個體化bean之前,相當于new這個bean之前
- postProcessAfterInstantiation: 執行個體化bean之後, 相當與new這個bean之後
- postProcessPropertyValues: bean 已經執行個體化以後, 在屬性注入階段觸發, @Autowired和@Resource基于此方法
- postProcessBeforeInitialization: 初始化bean之前, 相當于把bean注入spring上下文之前
- postProcessAfterInitialization: 初始化bean之後, 相當于把bean注入spring上下文之後
寫中間件和業務中,都能利用這個特性。比如對實作了某一類接口的bean在各個生命期間進行收集,或者對某個類型的bean進行統一的設值等等。
6.SmartInstantiationAwareBeanPostProcessor
org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
public class TestSmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("[TestSmartInstantiationAwareBeanPostProcessor] predictBeanType " + beanName);
return beanClass;
}
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("[TestSmartInstantiationAwareBeanPostProcessor] determineCandidateConstructors " + beanName);
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
System.out.println("[TestSmartInstantiationAwareBeanPostProcessor] getEarlyBeanReference " + beanName);
return bean;
}
}
- predictBeanType: 該觸發點發生在postProcessBeforeInstantiation之前, 這個方法用于預測Bean的類型, 傳回第一個預測成功的Class類型, 如果不能預測傳回null。當你調用BeanFactory.getType(name)時當通過bean的名字無法得到bean類型資訊時就調用該回調方法來決定類型資訊。
- determineCandidateConstructors: 該觸發點發生在postProcessBeforeInstantiation之後, 用于确定bean的構造函數, 傳回的是bean的是以構造函數清單, 可以通過此方法自定義選擇對應的構造器來執行個體化bean
- getEarlyBeanReference: 該觸發點發生在postProcessAfterInstantiation之後, 當有循環依賴的場景,當bean執行個體化好之後,為了防止有循環依賴,會提前暴露回調方法,用于bean執行個體化的後置處理。這個方法就是在提前暴露的回調方法中觸發。
7.BeanFactoryAware
org.springframework.beans.factory.BeanFactoryAware
org.springframework.beans.factory.BeanFactoryAware
發生在bean的執行個體化之後,注入屬性之前,也就是Setter之前。這個類的擴充點方法為setBeanFactory,可以拿到BeanFactory這個屬性。
public class TestBeanFactoryAware implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("[TestBeanFactoryAware] " + beanFactory.getBean(TestBeanFactoryAware.class).getClass().getSimpleName());
}
}
可以在bean執行個體化之後, 初始化之前, 拿到beanFactory, 然後對bean進行特殊化的定制, 或者将beanFactory拿到進行緩存, 日後使用。
8.ApplicationContextAwareProcessor
org.springframework.context.support.ApplicationContextAwareProcessor
org.springframework.context.support.ApplicationContextAwareProcessor
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 ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
6個擴充點: EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware, ApplicationStartupAware
9.BeanNameAware
org.springframework.beans.factory.BeanNameAware
org.springframework.beans.factory.BeanNameAware
public class NormalBeanA implements BeanNameAware{
public NormalBeanA() {
System.out.println("NormalBean constructor");
}
@Override
public void setBeanName(String name) {
System.out.println("[BeanNameAware] " + name);
}
}
觸發點為bean的初始化之前,
postProcessBeforeInitialization
方法之前, 可以通過在初始化bean之前拿到spring容器中注冊的的beanName, 修改beanName。
10.@PostConstruct
javax.annotation.PostConstruct
javax.annotation.PostConstruct
public class NormalBeanA {
public NormalBeanA() {
System.out.println("NormalBean constructor");
}
@PostConstruct
public void init(){
System.out.println("[PostConstruct] NormalBeanA");
}
}
觸發點是在postProcessBeforeInitialization之後,InitializingBean.afterPropertiesSet之前。
11.InitializingBean
org.springframework.beans.factory.InitializingBean
org.springframework.beans.factory.InitializingBean
初始化bean, 在方法
postProcessAfterInitialization
之前實作。
public class NormalBeanA implements InitializingBean{
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("[InitializingBean] NormalBeanA");
}
}
進行系統啟動的時候一些業務名額的初始化工作
12.FactoryBean
org.springframework.beans.factory.FactoryBean
org.springframework.beans.factory.FactoryBean
工廠Bean, Spring提供了70多個實作, 隐藏了複雜的bean的細節, 給上層提供了便利
public class TestFactoryBean implements FactoryBean<TestFactoryBean.TestFactoryInnerBean> {
@Override
public TestFactoryBean.TestFactoryInnerBean getObject() throws Exception {
System.out.println("[FactoryBean] getObject");
return new TestFactoryBean.TestFactoryInnerBean();
}
@Override
public Class<?> getObjectType() {
return TestFactoryBean.TestFactoryInnerBean.class;
}
@Override
public boolean isSingleton() {
return true;
}
public static class TestFactoryInnerBean{
}
}
可以通過這個類, 執行個體化bean作為一個代理, 比如為該對象的是以方法做一個攔截, 輸出一個日志資訊。
13.SmartInitializingSingleton
org.springframework.beans.factory.SmartInitializingSingleton
org.springframework.beans.factory.SmartInitializingSingleton
- afterSingletonsInstantiated: 在spring容器管理的所有單例對象(非懶加載對象)初始化完成之後調用的回調接口。在
之後執行。postProcessAfterInitialization
public class TestSmartInitializingSingleton implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("[TestSmartInitializingSingleton]");
}
}
可以對于所有單例對象初始化後, 做出一些業務處理
14.CommandLineRunner
org.springframework.boot.CommandLineRunner
org.springframework.boot.CommandLineRunner
public class TestCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("[TestCommandLineRunner]");
}
}
15.DisposableBean
org.springframework.beans.factory.DisposableBean
org.springframework.beans.factory.DisposableBean
- destroy: 對象銷毀時執行。
public class NormalBeanA implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("[DisposableBean] NormalBeanA");
}
}
16.ApplicationListener
org.springframework.context.ApplicationListener
org.springframework.context.ApplicationListener
- ContextRefreshedEvent: ApplicationContext 被初始化或重新整理時,該事件被釋出。這也可以在ConfigurableApplicationContext接口中使用 refresh()方法來發生。
- ContextStartedEvent: ConfigurableApplicationContext.started()啟動ApplicationContext, 釋出事件。
- ContextStoppedEvent: ConfigurableApplicationContext.stopped()停止ApplicationContext, 釋出事件。
- ContextClosedEvent: ConfigurableApplicationContext.closed()關閉ApplicationContext, 釋出事件。
- RequestHandledEvent: web-specific 事件, 告訴所有Bean Http 請求已經被服務。隻能應用于使用DispatcherServlet的Web應用。當Spring處理使用者請求結束後,系統會自動觸發該事件。