Spring: don't BeanDefinition&PostProcessor know something about it?

Keywords: Spring Attribute xml Java

Rice: I saw the source code of BeanDefinition, BeanFactoryPostProcessor and BeanPostProcessor these two days. Do you want to know

Melon: six six six, big man

Rice: last time we said that spring IOC container is a typical factory model

  • If we compare Spring to a large factory producing models, then. class files are raw materials. Bean definition is the mold to create the model. Whether it's traditional XML or later annotations, Spring will create a scanner to scan the. class files in the specified directory when it starts, and encapsulate the bean definitions one by one according to the annotations, implemented interfaces and member variables of the files.
    • The more important attributes are id,class, constructor encapsulation class, attribute encapsulation class, factoryMethod, etc
  • Before initializing the object, Spring will finish parsing the BeanDefinition object and load it into the List container beanDefinitionNames, and then start traversing the container and creating the object according to BeanDefinition

Papaya: I understand. It is a template for creating bean s, similar to the class on which java creates objects. So what are two long words?

Rice: ignore the old suffix. Let's see if Bean factory and Bean are very friendly. PostProcessor is translated into a PostProcessor. Let's just think of it as a processor

  • BeanFactory is a bean factory, which can get and modify the properties of BeanDefinition, and then affect the objects created later.
  • Bean is the object of Spring, and these processors are the procedures to deal with all aspects of bean object, including properties, annotations and methods

Cauliflower: with a vague concept, I don 't know how to be sharp

Rice: let's see demo

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;

/**
 * Get the initialized BeanFactory. At this time, the bean has not been instantiated
 *
 * @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 Nonparametric structure 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 class
@Test
public void test() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.vip.qc.postprocessor");
    ProcessorT processorT = (ProcessorT) context.getBean("processorT");
    System.out.println(processorT);
}

// result
BeanFactoryPostProcessor a null -> 1
ProcessorT Nonparametric structure a:null-> 2
BeanPostProcessor BeforeInitialization a:1-> 3
BeanPostProcessor AfterInitialization a:3-> 4
ProcessorT{a='4'}

 

  • BeanFactoryPostProcessor can get the BeanDefinition of the object to set the property value before the object is initialized

  • In the process, we set the values of 1, 2, 3 and 4 for property a respectively. Finally, we got a value of 4

Chagua: I think I understand. BeanFactoryPostProcessor can get BeanFactory objects, get all beandefinitions in them and intervene them. The bean processor actually processes the bean after it has been created

Rice: that's right. This is our own intervention demo. Limited to space, you can take a look at Spring's own implementation source code for these two interfaces. Here are some important recommendations

  • ConfigurationClassPostProcessor implements BeanFactoryPostProcessor sub interface
    • Complete collection and analysis of @ Configuration, @ Component, @ ComponentScan, @ Bean, @ Import, @ ImportSource annotations
    • @The Bean annotation will be encapsulated in the factoryMethod attribute in the Bean definition of the Bean, and instantiated separately
  • CommonAnnotationBeanPostProcessor implement BeanPostProcessor
    • Complete@ PostConstruct@PreDestroy@Resource Collection and analysis of annotations
    • @PostConstruct will start after the object is initialized and the attribute rendering is completed
    • @Resource annotation (see below)
  • Autowired annotation BeanPostProcessor to implement BeanPostProcessor
    • Complete@ Autowired@Value Collection and analysis of annotations
    • After the object initialization is completed, the annotation will be collected first, then the attribute rendering will be performed, and the populateBean method will be called. The policy mode call will be used to implement the interface to parse the annotation. The @ Autowired and @ Value annotation will call the getBean method to initiate the injection of dependency attributes
  • The entry class of AbstractAutoProxyCreator is also the implementation of BeanPostProcessor

Chagua: don't worry, I won't watch it. It's so complicated. It's hard to listen

Rice: it's you! It's OK. We will talk about these things when we have a chance to talk about the bean life cycle. I'll do it again

Posted by border20 on Mon, 15 Jun 2020 20:44:44 -0700