日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

springboot:BeanPostProcessor示例及分析

發布時間:2023/12/3 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot:BeanPostProcessor示例及分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【README】

1,本文主要分析 BeanPostProcessor 的作用, 開發方式;

2,BeanPostProcessor 是bean后置處理器, 簡而言之就是bean被創建好了,之后如果需要對其屬性進行修改,則 需要使用? BeanPostProcessor 來起作用;

3,本文還順帶介紹了? InitializingBean 接口;?

? 啥都不說,先上代碼;?

4, sprinboot的 后置處理器PostProcessor列表小結(這里只講了4個):

  • BeanPostProcessor, bean實例化后的 處理器 ;?
  • InstantiationAwareBeanPostProcessor,實例化裝配bean后置處理器,在bean實例化前后干點事情的處理器, 顯然執行順序先于? BeanPostProcessor
  • SmartInstantiationAwareBeanPostProcessor, 智能實例化裝配bean后置處理器,同 InstantiationAwareBeanPostProcessor,不過方法比 InstantiationAwareBeanPostProcessor 多;
  • DestructionAwareBeanPostProcessor, bean銷毀時的處理器;

  • 【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,結果解析

    很明顯, 程序執行順序為

  • bean構造器;
  • BeanPostProcessor-bean后置處理器的 postProcessBeforeInitialization 方法;
  • InitializingBean的afterPropertiesSet() 方法;
  • BeanPostProcessor-bean后置處理器的 postProcessAfterInitialization 方法;

  • 【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 實例。

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { ?

    ?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后置處理器的? postProcessBeforeInitialization ;
  • 初始化bean接口的? afterPropertiesSet ;
  • 后置處理器的? postProcessAfterInitialization? ;
  • 【補充】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示例及分析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。