Spring:BeanDefinition&PostProcessor不瞭解一下嗎?

水稻:這兩天看了BeanDefinition和BeanFactoryPostProcessor還有BeanPostProcessor的源碼。要不要了解一下java

菜瓜:six six six,大佬請講spring

水稻:上次咱們說SpringIOC容器是一個典型的工廠模式ide

  • 假如咱們把Spring比做一個生產模型的大工廠,那麼.class文件就是原材料。而BeanDefinition就是建立模型的模具。無論是傳統的XML仍是後面的註解,Spring在啓動的時候都會建立一個掃描器去掃描指定目錄下的.class文件,並根據文件的註解,實現的接口以及成員變量將其封裝一個個的BeanDefinition。
    • 比較重要的屬性有id,class,構造函數封裝類,屬性封裝類,factoryMethod等
  • 在對象初始化以前Spring會完成BeanDefinition對象的解析並將其裝入List容器beanDefinitionNames中,而後開始遍歷該容器並根據BeanDefinition建立對象

菜瓜:sodasinei,BeanDefinition我瞭解了。它是建立bean的模板,相似於java建立對象依賴的class同樣。那還有兩個很長的單詞是啥呢?函數

水稻:忽略掉後面老長的後綴,咱們看BeanFactory和Bean是否是很親切。PostProcessor被翻譯成後置處理器,暫且咱們把它當作是處理器就行post

  • BeanFactory是bean工廠,它能夠獲取並修改BeanDefinition的屬性,進而影響後面建立的對象。
  • Bean就是Spring的對象,這些個處理器纔是真正處理bean對象的各個環節的工序,包括屬性,註解,方法

菜瓜:有了模糊的概念,不明覺厲測試

水稻:來,看demothis

package com.vip.qc.postprocessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
 * 獲取初始化好的BeanFactory,此時還未進行bean的實例化
 *
 * @author QuCheng on 2020/6/14.
 */
@Component
public class BeanFactoryPostProcessorT implements BeanFactoryPostProcessor {

    public static final String BEAN_NAME = "processorT";

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition initializingBeanT = beanFactory.getBeanDefinition(BEAN_NAME);
        MutablePropertyValues propertyValues = initializingBeanT.getPropertyValues();
        String pName = "a";
        System.out.println("BeanFactoryPostProcessor a " + propertyValues.getPropertyValue(pName) + " -> 1");
        propertyValues.addPropertyValue(pName, "1");
    }
}


package com.vip.qc.postprocessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @author QuCheng on 2020/6/14.
 */
@Component
public class BeanPostProcessorT implements BeanPostProcessor {

    public static final String beanNameT = "processorT";

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanNameT.equals(beanName)) {
            ProcessorT processorT = ((ProcessorT) bean);
            System.out.println("BeanPostProcessor BeforeInitialization  a:" + processorT.getA() + "-> 3");
            processorT.setA("3");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanNameT.equals(beanName)){
            ProcessorT processorT = ((ProcessorT) bean);
            System.out.println("BeanPostProcessor AfterInitialization  a:" + processorT.getA() + "-> 4");
            processorT.setA("4");
        }
        return bean;
    }

}


package com.vip.qc.postprocessor;

import org.springframework.stereotype.Component;

/**
 * @author QuCheng on 2020/6/14.
 */
@Component
public class ProcessorT {

    public ProcessorT() {
        System.out.println("ProcessorT 無參構造 a:" + a + "-> 2" );
        a = "2";
    }

    private String a;

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "ProcessorT{" +
                "a='" + a + '\'' +
                '}';
    }
}

// 測試類
@Test
public void test() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.vip.qc.postprocessor");
    ProcessorT processorT = (ProcessorT) context.getBean("processorT");
    System.out.println(processorT);
}

// 結果
BeanFactoryPostProcessor a null -> 1
ProcessorT 無參構造 a:null-> 2
BeanPostProcessor BeforeInitialization a:1-> 3
BeanPostProcessor AfterInitialization a:3-> 4
ProcessorT{a='4'}

 

  • BeanFactoryPostProcessor在對象還未初始化前能夠拿到對象的BeanDefinition對其設置屬性值  spa

  • 過程當中咱們分別對屬性a設置了1,2,3,4的值。最後咱們拿到的值爲4

菜瓜:好像看懂了。BeanFactoryPostProcessor能夠拿到BeanFactory對象,獲取裏面全部的BeanDefinition並可對其進行干預。BeanPostProcessor實際上是在bean已經被建立完成以後進行加工操做翻譯

水稻:沒錯。這是咱們本身進行干預的demo。限於篇幅有限,你能夠去看一下Spring本身對於這兩個接口的實現源碼。比較重要的推薦下面幾個code

  • ConfigurationClassPostProcessor 實現BeanFactoryPostProcessor子接口
    • 完成對@Configuration、@Component、@ComponentScan、@Bean、@Import、@ImportSource註解的蒐集和解析
    • @Bean註解會被封裝成所在Bean的BeanDefinition中的factoryMethod屬性中,單獨進行實例化
  • CommonAnnotationBeanPostProcessor 實現 BeanPostProcessor
    • 完成@PostConstruct@PreDestroy@Resource註解的蒐集和解析工做
    • @PostConstruct會在對象初始化且屬性渲染完成後進行
    • @Resource註解(參照下面)
  • AutowiredAnnotationBeanPostProcessor 實現 BeanPostProcessor
    • 完成@Autowired@Value註解的蒐集和解析工做
    • 在對象初始化完成以後會先進行註解的蒐集,而後進行屬性渲染調用populateBean方法,使用策略模式調用實現接口對註解進行解析,有@Autowired和@Value註解會調用getBean方法發起對依賴屬性的注入
  • AbstractAutoProxyCreator的入口類也是實現的BeanPostProcessor

菜瓜:你放心,我不會看的。這麼複雜的東西,聽着都費勁

水稻:不愧是你!沒事,有機會聊bean的生命週期的時候我們還會說到這些東西。到時候再刷一遍

相關文章
相關標籤/搜索