springboot:BeanPostProcessor示例及分析
【README】
1,本文主要分析 BeanPostProcessor 的作用, 開發方式;
2,BeanPostProcessor 是bean后置處理器, 簡而言之就是bean被創建好了,之后如果需要對其屬性進行修改,則 需要使用? BeanPostProcessor 來起作用;
3,本文還順帶介紹了? InitializingBean 接口;?
? 啥都不說,先上代碼;?
4, sprinboot的 后置處理器PostProcessor列表小結(這里只講了4個):
【1】 BeanPostProcessor 例子
0,借助 BeanPostProcessor ,InitializingBean 在bean創建完成后 進行日志打印;
1,bean接口與類(類實現了 初始化bean接口InitializeingBean )
public interface HelloService {public String sayHello(); }@Service("helloServiceImpl1") public class HelloServiceImpl1 implements HelloService, InitializingBean {public HelloServiceImpl1(){System.out.println("HelloServiceImpl1 構造器");}@Overridepublic String sayHello() {return "你好我是HelloServiceImpl1";}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("HelloServiceImpl1.afterPropertiesSet() 方法");} }2,后置處理器實現類
/*** @Description bean后置處理器* @author xiao tang* @version 1.0.0* @createTime 2021年11月14日*/ @Component public class HelloPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 非自定義bean,直接返回if (!(bean instanceof HelloService)) {return bean;} else {// 自定義,打印日志System.out.printf("bean[%s]初始化前\n", beanName);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// 非自定義bean,直接返回if (!(bean instanceof HelloService)) {return bean;} else {// 自定義,打印日志System.out.printf("bean[%s]初始化后\n", beanName);}return bean;} }bean后置處理器作用, 在 bean創建完成后,可以通過? postProcessBeforeInitialization 和
postProcessAfterInitialization 修改bean的屬性;3,測試用例
@SpringBootTest class Springbt02Config02ApplicationTests {@AutowiredApplicationContext applicationContext;@Testvoid contextLoads() throws SQLException {HelloServiceImpl1 impl1 = (HelloServiceImpl1) applicationContext.getBean("helloServiceImpl1");System.out.println(impl1.sayHello());} }打印結果:
HelloServiceImpl1 構造器
bean[helloServiceImpl1]初始化前
HelloServiceImpl1.afterPropertiesSet() 方法
bean[helloServiceImpl1]初始化后
你好我是HelloServiceImpl1
?4,結果解析
很明顯, 程序執行順序為
【2】BeanPostProcessor 方法調用順序
【2.1】如何走到? postProcessBeforeInitialization() 方法?
1, 路徑如下:
從 SpringApplication.run() 方法走;?
?
?
接著調用 springboot 創建 bean的方法,即 DefaultListableBeanFactory.preInstantiateSingletons() 方法;
?然后調用 AbstractAutowireCapableBeanFactory.doCreateBean() 方法創建給定bean;方法參數:
實際創建指定的bean。 預創建處理此時已經發生,例如 檢查 postProcessBeforeInstantiation 回調。
區分默認 bean 實例化、工廠方法的使用和自動裝配構造函數。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) ? throws BeanCreationException {
創建完成后,調用? AbstractAutowireCapableBeanFactory.initializeBean() 方法初始化給定bean(bean的創建與初始化是 兩回事), 方法說明如下:
初始化給定的 bean 實例,應用工廠回調以及 init 方法和 bean 后處理器。
從 createBean 調用傳統定義的 bean,從 initializeBean 調用現有 bean 實例。
?AbstractAutowireCapableBeanFactory.initializeBean() 方法源碼;
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) { // 調用bean后置處理器的 postProcessBeforeInitialization() 方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try { // 調用 InitializingBean 的 afterPropertiesSet() 方法 invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) { // 調用bean后置處理器的 postProcessAfterInitialization() 方法wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean; }?這里非常清楚的說明了 bean后置處理器, 初始化bean的方法調用順序為:
【補充】bean后置處理器
?【2.2】 BeanPostProcessor 接口 api
【2.2.1】BeanPostProcessor 類說明
1,允許自定義修改新 bean 實例的工廠鉤子 - 例如,檢查標記接口或使用代理包裝 bean。
通常,通過標記接口等填充 bean 的后處理器將實現 postProcessBeforeInitialization,而使用代理包裝 bean 的后處理器通常將實現 postProcessAfterInitialization。
2,登記
ApplicationContext 可以在其 bean 定義中自動檢測 BeanPostProcessor bean,并將這些后處理器應用于隨后創建的任何 bean。普通的 BeanFactory 允許以編程方式注冊后處理器,將它們應用于通過 bean 工廠創建的所有 bean。
3,排序
在 ApplicationContext 中自動檢測的 BeanPostProcessor bean 將根據 org.springframework.core.PriorityOrdered 和 org.springframework.core.Ordered 語義進行排序。
相比之下,使用BeanFactory以編程方式注冊的 BeanPostProcessor bean 將使用注冊順序;對于以編程方式注冊的后處理器(BeanPostProcessor bean ),會忽略掉實現 PriorityOrdered 或 Ordered 接口的排序。此外,@Order 注釋不會被 BeanPostProcessor bean 考慮在內。
// bean后置處理器 public interface BeanPostProcessor {@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}【2.2.2】 ?postProcessBeforeInitialization 方法說明
在任何 bean 初始化回調(如 InitializingBean 的 afterPropertiesSet 或自定義初始化方法)之前,將此 BeanPostProcessor 應用于給定的新 bean 實例。
bean 已經被填充了屬性值。 返回的 bean 實例可能是原始實例的包裝器。
默認實現按原樣返回給定的 bean。
說白了 ,就是在 InitiaizingBean.afterPropertiesSet() 之前執行;
@Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean; }【2.2.3】 postProcessAfterInitialization 方法說明
說白了 ,就是在 InitiaizingBean.afterPropertiesSet() 之后執行;
在任何 bean 初始化回調(如 InitializingBean 的 afterPropertiesSet 或自定義初始化方法)之后,將此 BeanPostProcessor 應用于給定的新 bean 實例。 bean 已經被填充了屬性值。 返回的 bean 實例可能是原始實例的包裝器。
在 FactoryBean 的情況下,將為 FactoryBean 實例和 FactoryBean 創建的對象調用此回調(從 Spring 2.0 開始)。 后處理器可以通過相應的 bean instanceof FactoryBean 檢查來決定是應用于 FactoryBean 或創建的對象還是兩者。
與所有其他 BeanPostProcessor 回調相比,此回調也將在由 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 方法觸發的短路后調用。
默認實現按原樣返回給定的 bean。
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean; }【3】InitializingBean
【3.1】InitializingBean? 類說明
由 BeanFactory 設置所有屬性后需要響應的 bean 實現的接口:例如 執行自定義初始化,或僅檢查是否已設置所有必需屬性。
public interface InitializingBean { void afterPropertiesSet() throws Exception; }【3.1.1】? afterPropertiesSet 方法說明
在設置所有 bean 屬性并滿足 BeanFactoryAware、ApplicationContextAware 等要求后,由 包裹的BeanFactory 調用。
此方法允許 bean 實例在設置所有 bean 屬性后執行其整體配置和最終初始化的驗證。
總結
以上是生活随笔為你收集整理的springboot:BeanPostProcessor示例及分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring-kafka整合:Kafka
- 下一篇: 哪些电脑是专业显卡(哪个是电脑显卡)