亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺談Spring中幾個(gè)PostProcessor的區(qū)別與聯(lián)系

 更新時(shí)間:2021年08月13日 10:55:09   作者:碩子鴿  
這篇文章主要介紹了淺談Spring中幾個(gè)PostProcessor的區(qū)別與聯(lián)系,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring幾個(gè)PostProcessor的區(qū)別

首先明確 Bean 的生命周期:

  • 首先注冊(cè) Bean 的定義信息;
  • 然后創(chuàng)建 Bean 的實(shí)例;
  • 最后初始化 Bean ,放入容器中。

按照?qǐng)?zhí)行的順序,可以分為以下幾個(gè)步驟:

BeanDefinitionRegistryPostProcessor 是在注冊(cè) Bean 定義信息前后調(diào)用;

BeanFactoryPostProcessor 是在創(chuàng)建 Bean 前后調(diào)用;

BeanPostProcessor 是在初始化 Bean 前后調(diào)用;

其中 BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子類,所以可以使用前者代替后者實(shí)現(xiàn)功能。

查看 IOC 容器創(chuàng)建時(shí)的調(diào)用流程

refresh 方法的代碼如下:

// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();

其中的 invokeBeanFactoryPostProcessors 就執(zhí)行了注冊(cè)定義信息和創(chuàng)建 Bean 的方法;而 finishBeanFactoryInitialization 執(zhí)行了初始化 Bean 的方法。

具體的執(zhí)行順序大家可以自行打斷點(diǎn)調(diào)試,由于涉及的源碼過(guò)多,這里不再展示。

spring-postProcessor的執(zhí)行時(shí)機(jī)

spring bean 的生命周期粗糙的分為以下步驟。

實(shí)例化(創(chuàng)建一個(gè)屬性都為空的對(duì)象)---------》屬性填充(populateBean,下文中這個(gè)步驟我都稱為初始化)-----------》init方法的執(zhí)行(invokerInitMethods,下文稱為init)

postprocessor的方法就是穿插在這三個(gè)大的步驟中。

BeanPostProcessor:

postProcessBeforeInitialization調(diào)用時(shí)機(jī)

向上找調(diào)用者:

繼續(xù)向上:

看以看出populateBean(初始化bean)-------------------》beanpostBeforeInitialization---------------------------------->invokeinitMethods(配置的init-method)

postProcessAfterInitialization調(diào)用時(shí)機(jī):

向上:

可以看出在init-method方法之后

看以看出populateBean(初始化bean)-------------------》beanpostBeforeInitialization---------------------------------->invokeinitMethods(配置的init-method)------->postProcessAfterInitialization

public class MBeanPostProcessor implements BeanPostProcessor { 
    @Override
    //populateBean之后   invokeinitMethods之前
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("post bean before! :"+beanName);
        return bean;
    }
 
    @Override
    //invokeinitMethods之后
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("post bean after!"+beanName);
        return bean;
    }
}

另一個(gè)重要的是:

InstantiationAwareBeanPostProcessor

postProcessBeforeInstantiation調(diào)用時(shí)機(jī):

向上找調(diào)用者:

繼續(xù)向上:

可以看出是在實(shí)例化之前:(也就是反射創(chuàng)建對(duì)象之前,如果postProcessBeforeInstantiation創(chuàng)建了一個(gè)非空的對(duì)象,則不會(huì)走實(shí)例化步驟。

postProcessAfterInstantiation調(diào)用時(shí)機(jī):

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   PropertyValues pvs = mbd.getPropertyValues();
 
   if (bw == null) {
      if (!pvs.isEmpty()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         // Skip property population phase for null instance.
         return;
      }
   }
 
   // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
   // state of the bean before properties are set. This can be used, for example,
   // to support styles of field injection.
   boolean continueWithPropertyPopulation = true;
 
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            //在這里執(zhí)行
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }
 
   if (!continueWithPropertyPopulation) {
      return;
   }
 省略。。。。。 
   applyPropertyValues(beanName, mbd, bw, pvs);
}

可以看出是在在初始化之前,具體是屬性填充之前。(初始化之前,實(shí)例化之后) 如果返回fales,則不會(huì)繼續(xù)初始化,即不會(huì)屬性填充。

postProcessPropertyValues調(diào)用時(shí)機(jī):

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   PropertyValues pvs = mbd.getPropertyValues(); 
   if (bw == null) {
      if (!pvs.isEmpty()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         // Skip property population phase for null instance.
         return;
      }
   }
 
   // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
   // state of the bean before properties are set. This can be used, for example,
   // to support styles of field injection.
   boolean continueWithPropertyPopulation = true;
 
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }
 
   if (!continueWithPropertyPopulation) {
      return;
   }
 
   if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
 
      // Add property values based on autowire by name if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }
 
      // Add property values based on autowire by type if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      } 
      pvs = newPvs;
   }
 
   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
 
   if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
         for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
               InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
               pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvs == null) {
                  return;
               }
            }
         }
      }
      if (needsDepCheck) {
         checkDependencies(beanName, mbd, filteredPds, pvs);
      }
   } 
   applyPropertyValues(beanName, mbd, bw, pvs);
}

在postProcessAfterInstantiation之后,applyPropertyValues之前。(屬性填充之前修改屬性值)

總結(jié): 執(zhí)行順序

  • 1.postProcessBeforeInstantiation(實(shí)現(xiàn)這個(gè)方法可以做自定義實(shí)例化)
  • 2.實(shí)例化
  • 3.postProcessAfterInstantiation(是否要初始化)
  • 4.postProcessPropertyValues(修改屬性)
  • 5.初始化(屬性填充)(populateBean)
  • 6.postProcesstBeforeInitialization( 自定義init方法執(zhí)行之前)
  • 7.invokeinitMethods(執(zhí)行自定義的init方法)
  • 8.postProcessAfterInitialization(自定義init方法執(zhí)行之后)

如果加上aware

  • 1.postProcessBeforeInstantiation(實(shí)現(xiàn)這個(gè)方法可以做自定義實(shí)例化)
  • 2.實(shí)例化
  • 3.postProcessAfterInstantiation(是否要初始化)
  • 4.postProcessPropertyValues(修改屬性)
  • 5.初始化(屬性填充)(populateBean)
  • 6.postProcesstBeforeInitialization( 自定義init方法執(zhí)行之前)
  • 7.invokeAwareMethod
  • 8.invokeinitMethods(執(zhí)行自定義的init方法)
  • 9.postProcessAfterInitialization(自定義init方法執(zhí)行之后)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • mapstruct的用法之qualifiedByName示例詳解

    mapstruct的用法之qualifiedByName示例詳解

    qualifiedByName的意思就是使用這個(gè)Mapper接口中的指定的默認(rèn)方法去處理這個(gè)屬性的轉(zhuǎn)換,而不是簡(jiǎn)單的get?set,今天通過(guò)本文給大家介紹下mapstruct的用法之qualifiedByName示例詳解,感興趣的朋友一起看看吧
    2022-04-04
  • SpringBoot設(shè)置首頁(yè)(默認(rèn)頁(yè))跳轉(zhuǎn)功能的實(shí)現(xiàn)方案

    SpringBoot設(shè)置首頁(yè)(默認(rèn)頁(yè))跳轉(zhuǎn)功能的實(shí)現(xiàn)方案

    這篇文章主要介紹了SpringBoot設(shè)置首頁(yè)(默認(rèn)頁(yè))跳轉(zhuǎn)功能,本文通過(guò)兩種方案,給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-07-07
  • java多線程中斷代碼詳解

    java多線程中斷代碼詳解

    這篇文章主要介紹了java多線程中斷代碼詳解,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Redis6搭建集群并在SpringBoot中使用RedisTemplate的實(shí)現(xiàn)

    Redis6搭建集群并在SpringBoot中使用RedisTemplate的實(shí)現(xiàn)

    本文主要介紹了Redis6搭建集群并在SpringBoot中使用RedisTemplate,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Spring?Boot?3.x?集成?Feign的詳細(xì)過(guò)程

    Spring?Boot?3.x?集成?Feign的詳細(xì)過(guò)程

    本文闡述了如何在SpringBoot3.x中集成Feign,以實(shí)現(xiàn)微服務(wù)之間的調(diào)用,主要步驟包括:搭建chain-common服務(wù),創(chuàng)建chain-starter/chain-feign-starter服務(wù),集成Feign到chain-system和chain-iot-channel服務(wù),配置Feign,感興趣的朋友一起看看吧
    2024-09-09
  • springmvc+spring+mybatis實(shí)現(xiàn)用戶登錄功能(上)

    springmvc+spring+mybatis實(shí)現(xiàn)用戶登錄功能(上)

    這篇文章主要為大家詳細(xì)介紹了springmvc+spring+mybatis實(shí)現(xiàn)用戶登錄功能,比較基礎(chǔ)的學(xué)習(xí)教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • SpringBoot整合定時(shí)任務(wù)的方法

    SpringBoot整合定時(shí)任務(wù)的方法

    通過(guò) ThreadPoolExecutor 可以實(shí)現(xiàn)各式各樣的自定義線程池,而 ScheduledThreadPoolExecutor 類則在自定義線程池的基礎(chǔ)上增加了周期性執(zhí)行任務(wù)的功能,這篇文章主要介紹了SpringBoot整合定時(shí)任務(wù),需要的朋友可以參考下
    2024-05-05
  • MyBatis動(dòng)態(tài)sql查詢及多參數(shù)查詢方式

    MyBatis動(dòng)態(tài)sql查詢及多參數(shù)查詢方式

    這篇文章主要介紹了MyBatis動(dòng)態(tài)sql查詢及多參數(shù)查詢方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • mybatis-plus插入失敗的問(wèn)題及解決

    mybatis-plus插入失敗的問(wèn)題及解決

    這篇文章主要介紹了mybatis-plus插入失敗的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Java線程池使用與原理詳解

    Java線程池使用與原理詳解

    這篇文章主要為大家詳細(xì)介紹了Java線程池使用與原理的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評(píng)論