When Spring loaded bean constructors when calls, @ PostConstruct when calls, implements the BeanPostProcessor interface of bean postProcessAfterInitialization and postProcessBe When is foreInitialization called? Do you know? If it is clear, you can just ignore this article!!

Recently, several new people came and were asked a knowledge point related to the bean life cycle. After solving the problem of new people, I wrote a demo to clearly describe the life cycle of the whole bean.

Note that the following demo has five classes, which may cause discomfort for some people. It is suggested that you can skip to the last to see the final summary, or download the source code to run. Demo address: github.com/wiatingpub/…

Give me a demo

First, we present a class that implements BeanFactoryPostProcessor. The purpose is to make it clear when the postProcessBeanFactory interface is called.

/ * * * * / @ spring BeanFactoryPostProcessor is bean factory processor Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { publicMyBeanFactoryPostProcessor() {
        super();
        System.out.println(BeanFactoryPostProcessor implements the constructor of the postProcessBeanFactory class.); } // Allow us to modify the properties of all beans in the factory after they have been loaded but before they are initialized. Before the operation function in the construction of the corresponding bean @ Override public void postProcessBeanFactory (ConfigurableListableBeanFactory arg0) throws BeansException { System.out .println("From MyBeanFactoryPostProcessor [spring BeanFactoryPostProcessor. PostProcessBeanFactory],"); / / get all of the Spring beanName String [] beanStr = arg0. GetBeanDefinitionNames (); // Loop printfor (String beanName : beanStr) {
            System.out.print("bean name:" + beanName + ";"); } System.out.println(); }} here is an implementation of a BeanPostProcessor classes, the purpose is to see postProcessAfterInitialization, postProcessBeforeInitialization call point in time. /** * BeanPostProcessor */ @component public class MyBeanPostProcessor implements BeanPostProcessor { publicMyBeanPostProcessor() {
        super();
        System.out.println("[MyBeanPostProcessor] BeanPostProcessor implementation class constructor"); } // when instantiation and dependency injection are complete, In the call display initialization completed before some custom business @ Override public Object postProcessAfterInitialization (Object arg0, String arg1) throws BeansException {if (arg0.getClass() == TestBeanA.class || arg0.getClass() == TestBeanB.class) {
            System.out
                    .println("From MyBeanPostProcessor BeanPostProcessor. PostProcessAfterInitialization 】 【, beanName:" + arg1);
        }
        returnarg0; } / / instantiate, dependency injection, done after the initial some custom business @ Override public Object postProcessBeforeInitialization (Object arg0, String arg1) throws BeansException {if (arg0.getClass() == TestBeanA.class || arg0.getClass() == TestBeanB.class) {
            System.out
                    .println("From MyBeanPostProcessor BeanPostProcessor. PostProcessBeforeInitialization 】 【, beanName:" + arg1);
        }
        returnarg0; }}Copy the code

Here is inherited InstantiationAwareBeanPostProcessorAdapter subclasses, The purpose is to see postProcessBeforeInitialization, postProcessAfterInitialization, are called postProcessPropertyValues point in time.

/** * Adapter class, Base class is the implementation class BeanPostProcessor * / @ Component public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { publicMyInstantiationAwareBeanPostProcessor() {
        super();
        System.out
                .println("[MyInstantiationAwareBeanPostProcessor] InstantiationAwareBeanPostProcessorAdapter implementation class constructor"); } / / interface method, instantiate the beans before call @ Override public Object postProcessBeforeInitialization (Object Bean, String beanName) throws BeansException {if (bean.getClass() == TestBeanA.class || bean.getClass() == TestBeanB.class) {
            System.out
                    .println("From MyInstantiationAwareBeanPostProcessor InstantiationAwareBeanPostProcessorAdapter. PostProcessBeforeInitialization 】 【, beanName:" + beanName);

        }
        returnbean; } / / interface method, instantiate the Bean called after @ Override public Object postProcessAfterInitialization (Object Bean, String beanName) throws BeansException {if (bean.getClass() == TestBeanA.class || bean.getClass() == TestBeanB.class) {
            System.out
                    .println("From MyInstantiationAwareBeanPostProcessor InstantiationAwareBeanPostProcessorAdapter. PostProcessAfterInitialization 】 【, beanName:" + beanName);
        }

        returnbean; } / / interface method, set up a property called @ Override public PropertyValues postProcessPropertyValues (PropertyValues PVS. PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {if (bean.getClass() == TestBeanA.class || bean.getClass() == TestBeanB.class) {
            System.out
                    .println("From MyInstantiationAwareBeanPostProcessor InstantiationAwareBeanPostProcessorAdapter. PostProcessPropertyValues 】 【, beanName:" + beanName);
        }

        return pvs;
    }
Copy the code

The cow force, directly to the applicationContext. XML injection and implements BeanFactoryAware BeanNameAware, InitializingBean and DisposableBean four interface class, The purpose is to clearly see when several of the following interfaces are called.

public class TestBeanA implements BeanFactoryAware, BeanNameAware,
        InitializingBean, DisposableBean {

    private String name;
    private String address;
    private int phone;

    private BeanFactory beanFactory;
    private String beanName;

    @PostConstruct
    public void init() {
        System.out.println([TestBeanA.@PostConstruct]);
    }

    public TestBeanA() {
        System.out.println("[TestBeanA. Default constructor]");
    }

    public TestBeanA(String name) {
        System.out.println("[TestBeanA. Parameter constructor]");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getPhone() {
        return phone;
    }

    public void setPhone(int phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "TestBeanA [address=" + address + ", name=" + name + ", phone="
                + phone + "]"; } // This is BeanFactoryAware @override public voidsetBeanFactory(BeanFactory arg0) throws BeansException {
        System.out
                .println("From TestBeanA BeanFactoryAware. SetBeanFactory 】 【"); this.beanFactory = arg0; } // This is BeanNameAware interface method @override public voidsetBeanName(String arg0) {
        System.out.println("From TestBeanA BeanNameAware. SetBeanName 】 【"); this.beanName = arg0; @override public void afterPropertiesSet() throws Exception {system.out.println () {Override public void afterPropertiesSet() throws Exception {system.out.println ("From TestBeanA InitializingBean. AfterPropertiesSet 】 【"); Override public void destroy() throws Exception {system.out.println ("[diposiblebean. destory] from TestBeanA"); } // The initialization method specified by the init-method property of <bean> public voidmyInit() {
        System.out.println("【TestBeanA.myInit】"); } // The destruction-method initializer specified by the <bean> property public voidmyDestory() {
        System.out.println("【TestBeanA.destroy-method】"); }}Copy the code

The purpose of TestBeanB is simple, to see how Spring loads beans when the internal data members have other container beans.

@Component
public class TestBeanB {

    @Autowired
    private TestBeanA testBeanA;

    public TestBeanB() {
        System.out.println([TestBeanB. Default constructor]); }}Copy the code

This is the startup class.

@SpringBootApplication
@ImportResource(locations = {"classpath:applicationContext.xml"}) public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}Copy the code

Although SpringBoot is used, XML is also used to see when init-method and destroy-method are called.

<? xml version="1.0" encoding="UTF-8"? > <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="testBeanA" class="com.example.demo.bean.TestBeanA" init-method="myInit" destroy-method="myDestory">
        <property name="name" value="Follow wechat public account Fansay programming"/>
    </bean>
</beans>
Copy the code

A very long very long code is given, let’s look at the results of the run

Spring BeanFactoryPostProcessor implementation class 】 postProcessBeanFactory constructor, spring BeanFactoryPostProcessor. PostProcessBeanFactory 】 【 From MyBeanFactoryPostProcessor BeanPostProcessor MyBeanPostProcessor 】 【 implementation class constructor 【 MyInstantiationAwareBeanPostProcessor 】 InstantiationAwareBeanPostProcessorAdapter implementation class constructor TestBeanB. The default constructor 】 【 From InstantiationAwareBeanPostProcessorAdapter. PostProcessPropertyValues 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanB [testbeana. default constructor] From InstantiationAwareBeanPostProcessorAdapter. PostProcessPropertyValues 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanA BeanNameAware. SetBeanName from TestBeanA 】 【 BeanFactoryAware. SetBeanFactory 】 from TestBeanA From BeanPostProcessor. PostProcessBeforeInitialization 】 【 MyBeanPostProcessor, beanName:testBeanA From InstantiationAwareBeanPostProcessorAdapter. PostProcessBeforeInitialization 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanA 【 TestBeanA. @ PostConstruct 】 【 InitializingBean. AfterPropertiesSet 】 from TestBeanA TestBeanA. MyInit 】 【 From BeanPostProcessor. PostProcessAfterInitialization 】 【 MyBeanPostProcessor, beanName:testBeanA From InstantiationAwareBeanPostProcessorAdapter. PostProcessAfterInitialization 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanA from BeanPostProcessor. PostProcessBeforeInitialization 】 【 MyBeanPostProcessor, beanName:testBeanB From InstantiationAwareBeanPostProcessorAdapter. PostProcessBeforeInitialization 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanB from BeanPostProcessor. PostProcessAfterInitialization 】 【 MyBeanPostProcessor, beanName:testBeanB From InstantiationAwareBeanPostProcessorAdapter. PostProcessAfterInitialization 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanB 【 diposiblebean. destory】 from TestBeanA 【 testbeana.destroy-method 】Copy the code

It seems to be another section of nausea code after seeing dizzy brain swelling, but not square not square, directly into the analysis stage, with the analysis of the start is much simpler.

Through result analysis

First of all, from the

Spring BeanFactoryPostProcessor implementation class 】 postProcessBeanFactory constructor, spring BeanFactoryPostProcessor. PostProcessBeanFactory 】 【 From MyBeanFactoryPostProcessor BeanPostProcessor MyBeanPostProcessor 】 【 implementation class constructor InstantiationAwareBeanPostProcessorAdapter MyInstantiationAwareBeanPostProcessor 】 【 implementation class constructorCopy the code

It can be seen that the order of execution is:

  • Call postProcessBeanFactory to implement the constructor of the class

The BeanFactoryPostProcessor is the bean factory processor

  • Call the postProcessBeanFactory implementation function of the postProcessBeanFactory implementation class

The postProcessBeanFactory function allows you to modify the properties of all beans in the factory after they have been loaded but not initialized. You can also add property values

  • Call BeanPostProcessor to implement the constructor of the class

To add some of your own logic before and after bean instantiation, configuration, and other initialization methods, implement the interface BeanPostProcessor

  • Call InstantiationAwareBeanPostProcessorAdapter implementation class constructor

The adapter class, whose base class is the implementation class of the BeanPostProcessor

Again from

[TestBeanB. Default constructor] From InstantiationAwareBeanPostProcessorAdapter. PostProcessPropertyValues 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanB
Copy the code

As you can see, TestBeanB is scanned by the Spring container first, so the call order is

  • Default constructor for TestBeanB
  • Call InstantiationAwareBeanPostProcessorAdapter postProcessPropertyValues interface implementation class

PostProcessPropertyValues call when interface method, set up a property, to see through the experiment to instantiate a Bean will invoke the interface methods

Later, when instantiating TestBeanB, TestBeanA was internally injected, so Spring instantiated TestBeanA instead.

The next thing you see is the order in which TestBeanA is called during instantiation

[TestBeanA. Default constructor] From InstantiationAwareBeanPostProcessorAdapter. PostProcessPropertyValues 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanA BeanNameAware. SetBeanName from TestBeanA 】 【 BeanFactoryAware. SetBeanFactory 】 from TestBeanA From BeanPostProcessor. PostProcessBeforeInitialization 】 【 MyBeanPostProcessor, beanName:testBeanA From InstantiationAwareBeanPostProcessorAdapter. PostProcessBeforeInitialization 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanA 【 TestBeanA. @ PostConstruct 】 【 InitializingBean. AfterPropertiesSet 】 from TestBeanA TestBeanA. MyInit 】 【 From BeanPostProcessor. PostProcessAfterInitialization 】 【 MyBeanPostProcessor, beanName:testBeanA From InstantiationAwareBeanPostProcessorAdapter. PostProcessAfterInitialization 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanA
Copy the code
  • TestBeanA’s default constructor is called
  • Call InstantiationAwareBeanPostProcessorAdapter postProcessPropertyValues interface implementation class
  • Call the setBeanName interface of BeanNameAware

TestBeanA implements the interface BeanNameAware

  • Call the setBeanFactory interface of BeanFactoryAware

TestBeanA implements the interface BeanFactoryAware

  • Call the BeanPostProcessor postProcessBeforeInitialization interface
  • Call InstantiationAwareBeanPostProcessorAdapter postProcessBeforeInitialization interface
  • Call the @postconstruct function from TestBeanA
  • The afterPropertiesSet interface of the InitializingBean was called

You can see from the source that TestBeanA implements the interface InitializingBean

  • TestBeanA’s myInit interface is called

You can see that the init-method interface is configured on the init-method in the applicationContext

  • Call the BeanPostProcessor postProcessAfterInitialization interface implementation class
  • Call InstantiationAwareBeanPostProcessorAdapter postProcessAfterInitialization interfaces subclass

After TestBeanA is instantiated, TestBeanB is instantiated

From BeanPostProcessor. PostProcessBeforeInitialization 】 【 MyBeanPostProcessor, beanName:testBeanB From InstantiationAwareBeanPostProcessorAdapter. PostProcessBeforeInitialization 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanB from BeanPostProcessor. PostProcessAfterInitialization 】 【 MyBeanPostProcessor, beanName:testBeanB From InstantiationAwareBeanPostProcessorAdapter. PostProcessAfterInitialization 】 【 MyInstantiationAwareBeanPostProcessor, beanName:testBeanB
Copy the code
  • Call the BeanPostProcessor postProcessBeforeInitialization interface implementation class
  • Call InstantiationAwareBeanPostProcessorAdapter postProcessBeforeInitialization interfaces subclass
  • Call the BeanPostProcessor postProcessAfterInitialization interface implementation class
  • Call InstantiationAwareBeanPostProcessorAdapter postProcessAfterInitialization interfaces subclass

The last

【 diposiblebean.destory 】 from TestBeanA 【 testbeana.destroy-method 】Copy the code
  • Call the DeStory interface of the DiposibleBean implementation class

TestBeanA implements DiposibleBean and destroy

  • Call TestBeanA’s myDestory function

You can see that the myDestory interface is configured on the destroy-method in applicationContext.

Final summary

【 Super key, interview answer template, super cool 】

  • If a bean implements the BeanFactoryPostProcessor interface class, the bean is instantiated and the default constructor is called, followed by the postProcessBeanFactory interface
  • If a bean implements the BeanPostProcessor interface class, the bean is instantiated first, again calling the default constructor
  • If it have bean inherited InstantiationAwareBeanPostProcessorAdapter class to instantiate the bean, also calls the default constructor

Then you actually go through the life cycle of a bean

  • The bean’s default constructor is called first
  • If you have bean inherited InstantiationAwareBeanPostProcessorAdapter class, at the moment will call postProcessPropertyValues function
  • If the bean already implements the BeanNameAware interface, its implemented setBeanName method is called, passing in the bean ID value in the ApplicationContext.xml configuration file
  • If the bean already implements the BeanFactoryAware interface, its implementation of setBeanFactory is called, passing in the Spring factory itself
  • If there are other bean implements the BeanPostProcessor interface, will call postProcessBeforeInitialization (Object obj, String s) method, BeanPostProcessor is often used as a change to the Bean content, and since this is a method that calls that at the end of Bean initialization, it can also be applied to memory or caching techniques;
  • If there are other beans inherited InstantiationAwareBeanPostProcessorAdapter class, will call postProcessBeforeInitialization interface
  • If the bean has a function annotated @postconstruct, that function will be called at this point
  • If the bean implements the InitializingBean interface and overrides the afterPropertiesSet method, that method will be called at this point
  • If the bean has the init-method property configured in the Spring configuration file, its configured initialization method is automatically called.
  • If there are other bean implements the BeanPostProcessor interface, will call postProcessAfterInitialization (Object obj, String s) method
  • If there are other beans inherited InstantiationAwareBeanPostProcessorAdapter class, will call postProcessAfterInitialization interface

At this point, you can apply the Bean, which is Singleton, although it is possible to configure a non-Singleton in the Spring configuration file without going into details here.

Enter destruction stage

  • When the bean is no longer needed, it passes through the DisposableBean stage. If the bean implements the DisposableBean interface, its implementation’s destroy() method is called;
  • If the bean’s applicationContext.xml configuration has the destroy-method attribute configured, its configured destruction method is automatically called.

Java source code analysis, go language application, micro services, more dry goods welcome to pay attention to the public number: