Spring中使用前置和后置處理器的好處有哪些?
謝謝邀請!
其實無論是前置和后置,還是其他接口,都是Spring 可擴展性表現。下面將會說明 Spring的前置和后置處理器,以及在 Spring 源碼里執(zhí)行的時機。最后說明 Spring 其他接口的 說明
下面將從以下幾個方面進行說明:
前置處理器和后置處理器
Spring 的生命周期
Spring 生命周期所涉及的源碼
Spring 其他可擴展接口
前置處理器和后置處理器Spring 的后置處理器主要為 BeanFactoryPostProcessor 和 BeanPostProcessor
1、BeanFactoryPostProcessor
BeanFactoryPostProcessor 是針對BeanDefinition 級別的后置處理器,它可以修改Bean的 定義,調用該接口時,bean還沒有進行初始化,它只有一個方法如下:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
① 怎樣自定義BeanFactoryPostProcessor?
通過實現BeanFactoryPostProcessor 接口方法,來修改yjLog bean的加載方式。
② 使用場景有哪些 ?
比如我們配置數據庫信息時,經常使用占位符${username},那么 Spring在什么時候進行值的替換呢?
當BeanFactory 在 第一階段加載 完成配置信息時,保存的對象屬性信息還是以占位符的形式 存在,這個解析的工作是在 PropertySourcesPlaceholderConfigurer 中進行解析的。
從下面類圖看:
PropertySourcesPlaceholderConfigurer 實現了 BeanFactoryPostProcessor 的接口
在下面的方法執(zhí)行的替換:
③ 在Spring 源碼中是在什么時候執(zhí)行的??
調用鏈如下:
Spring 初始化的主要步驟如下:
BeanFactoryPostProcessor 的 調用是在下面方法中
// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);
執(zhí)行堆棧如下:
我們驗證一下:BeanFactoryPostProcessor 實在 BeanDefinition 都加載完成才調用的
執(zhí)行上述方法前:Beanfactory里的BeanDefiniton定義如下:
2、BeanFactoryPostProcessor
BeanFactoryPostProcessor 是針對getBean操作獲得的 對的后置處理器 。他有兩個方法,一個在Bean初始化前執(zhí)行,一個在初始化后執(zhí)行
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean;}
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean;}
① 怎樣自定義 BeanFactoryPostProcessor
② 在源碼的執(zhí)行位置
執(zhí)行堆棧如下:
調用步驟如下:
// 1.調用類的構造方法
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object exposedObject = bean;
try {
//2.給屬性賦值
populateBean(beanName, mbd, instanceWrapper);
//3.初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
1.調用類的構造 方法
2.給屬性賦值
3. 初始化
(1) 給 *Aware 接口復制
(2) 執(zhí)行 BeanPostProcessor postProcessBeforeInitialization
(3) 執(zhí)行 InitializingBean 接口方法,執(zhí)行 自定義的init-mathod
(4) 執(zhí)行 BeanPostProcessor postProcessAfterInitialization 方法
3、BeanDefinitionRegistryPostProcessor
執(zhí)行時機:所有的bean定義信息將要被加載到容器中,Bean實例還沒有被初始化。
BeanDefinitionRegistryPostProcessor 接口可以看作是BeanFactoryPostProcessor和ImportBeanDefinitionRegistrar的功能集合
既可以獲取和修改BeanDefinition的元數據,也可以實現BeanDefinition的注冊、移除等操作。
怎樣自定義一個 BeanFactoryPostProcessor
驗證 執(zhí)行時機:
此時registry 已經以Bean的 定義信息
spring 生命周期如下圖執(zhí)行步驟如下:
1、執(zhí)行構造函數
2、給屬性賦值
3、給調用*aware接口
4、執(zhí)行BeanPostProcessor前置方法
5、調用InitializingBean的接口afterPropertiesSet方法
6、調用自定義的init方法
@Component
public class Book {
public Book() {
System.out.println("book 的構造方法");
}
@PostConstruct
public void init() {
System.out.println("book 的PostConstruct標志的方法");
}
@PreDestroy
public void destory() {
System.out.println("book 的PreDestory標注的方法");
}
}
7、執(zhí)行BeanPostProcessor后置方法
8、調用 DisposableBean destroy 銷毀
9、調用自定義的銷毀方法
@PreDestroy
public void destory() {
System.out.println("book 的PreDestory標注的方法");
}
Spring 生命周期所涉及的源碼主要的代碼如下:
① instanceWrapper = createBeanInstance(beanName, mbd, args);
調用構造方法
② populateBean(beanName, mbd, instanceWrapper)
給屬性賦值
③ initializeBean(beanName, exposedObject, mbd); 方法如下
(1) invokeAwareMethods(beanName, bean);
執(zhí)行* Aware 接口
(2) BeanPostProcessor 前置方法
(3) invokeInitMethods
調用InitializingBean的接口afterPropertiesSet方法 或者自定義的init方法
④ 調用 BeanPostProcessor 后置方法
Spring 其他可擴展接口1、ImportBeanDefinitionRegistrar接口
2、FactoryBean接口
3、ApplicationListener
--------------------------
關注我,后續(xù)有更多的干貨分享!