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