preface

This is actually an interview question, which WAS asked by me in the interview with Baidu, but I didn’t answer it at that time (because I was really bad at it). Later, I looked for the answer on the Internet, but I was also at a loss when I saw the book Spring in Action, which has a general explanation of Bean declaration cycle but no code analysis. So look for information online, be sure to understand the Bean life cycle!

In fact, there is a complete Bean life cycle to check the JDK, which also verifies the book is one-sided, the most fresh information or check the original JDK!!

The full life cycle of the Bean

In traditional Java applications, the bean life cycle is simple: the bean is instantiated using the Java keyword new, and then the bean is ready for use. Once the bean is no longer in use, it is automatically garbage collected by Java.

In contrast, the life cycle of Spring managed beans is much more complex. It is important to understand the life cycle of beans correctly because Spring is very scalable for managing beans. Here is a Bean construction process

The life cycle of the Bean

As shown in the figure above, the life cycle of a Bean is quite complex. Here is a text description of each step in the figure above:

  1. Spring starts, finds and loads beans that need to be managed by Spring, and instantiates the beans
  2. After the Bean is instantiated, the import and value of the Bean is injected into the Bean’s properties
  3. Spring passes the Bean Id to the setBeanName() method if the Bean implements the BeanNameAware interface
  4. If the Bean implements the BeanFactoryAware interface, Spring calls the setBeanFactory() method, passing in the BeanFactory container instance
  5. If the Bean implements the ApplicationContextAware interface, Spring calls the Bean’s setApplicationContext() method, passing in a reference to the Bean’s application context
  6. If the Bean implements the BeanPostProcessor interface, the Spring would call their postProcessBeforeInitialization () method.
  7. If the Bean implements the InitializingBean interface, Spring calls their afterPropertiesSet() method. Similarly, if the bean declares an initialization method with init-method, that method will be called
  8. If the Bean implements the BeanPostProcessor interface, the Spring would call their postProcessAfterInitialization () method.
  9. At this point, the Bean is ready to be used by the application. They will reside in the application context until the application context is destroyed.
  10. If the bean implements the DisposableBean interface, Spring will call its destory() interface method, which will also be called if the bean uses destory-method to declare the destruction method.

The above is the core interface and lifecycle of beans in Spring, which is enough for the interview. But a glance through the JavaDoc documentation reveals that there are other interfaces involved in the initialization process:

From org. Springframework. Beans. Factory. The BeanFactory, all relevant interface as follows, the existing without annotation, emphatically put additional relevant interface on annotation

The full life cycle of the Bean

The explanation is as follows:

———————————— Initialization ————————————

  • BeanNameAware. SetBeanName () in creating the bean bean factory set the name of the bean, call, after the common attribute set in InitializinngBean. AfterPropertiesSet () method before calling
  • BeanClassLoaderAware.setBeanClassLoader(): after the general attribute set, InitializingBean. AfterPropertiesSet () before calling
  • BeanFactoryAware. SetBeanFactory () : the callback provides its own bean instance factory, after the common property is set, the InitializingBean. AfterPropertiesSet () or a custom initialization method before calling
  • EnvironmentAware.setEnvironment(): Sets the environment to be called when the component is in use
  • EmbeddedValueResolverAware.setEmbeddedValueResolver(): Sets StringValueResolver to resolve embedded range problems
  • ResourceLoaderAware.setResourceLoader()Called after a normal bean object, before afterPropertiesSet or custom init-Method, and before ApplicationContextAware.
  • ApplicationEventPublisherAware.setApplicationEventPublisher()Called after a normal bean property and before an afterPropertiesSet or custom initialization method is initialized. Called before ApplicationContextAware.
  • MessageSourceAware.setMessageSource()Called after a normal bean property, before an afterPropertiesSet or custom initialization method is initialized, and before ApplicationContextAware.
  • ApplicationContextAware. SetApplicationContext () : in common Bean object generated after the call, the InitializingBean. Before the afterPropertiesSet calls or user custom initialization method before. In ResourceLoaderAware setResourceLoader, ApplicationEventPublisherAware setApplicationEventPublisher, After MessageSourceAware.
  • ServletContextAware.setServletContext()Runtime Settings ServletContext, after the common bean initialization calls, in InitializingBean. Before the afterPropertiesSet calls, call after ApplicationContextAwareNote: This is at WebApplicationContext runtime
  • BeanPostProcessor.postProcessBeforeInitialization() : Applies the BeanPostProcessor given new bean instance at any bean initialization callback methods (such as InitializingBean. AfterPropertiesSet or custom initialization method) before the call. The bean will be ready to populate the value of the property. The returned bean sample may be wrapped in a plain object, and the default implementation returns a bean.
  • BeanPostProcessor.postProcessAfterInitialization() : Applies the BeanPostProcessor given new bean instance at any bean initialization callback methods (such as InitializingBean. AfterPropertiesSet or custom initialization method) after the call. The bean will be ready to populate the value of the property. The returned bean sample may be wrapped in a plain object
  • InitializingBean. AfterPropertiesSet () : is the BeanFactory in set all the bean property called after (and meet the BeanFactory and ApplicationContextAware).

— — — — — — — — — — — — destroyed

When the BeanFactory is closed, the Bean lifecycle calls the following methods:

  • DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(): Applies this BeanPostProcessor to the given bean instance prior to destruction. The ability to call custom callbacks, such as the destruction and custom destruction methods of DisposableBean, which only apply to singleton beans (including internal beans) in the factory
  • Implements a custom deStory () method

Second, Bean lifecycle validation

To verify the Bean lifecycle process, there are two forms: one for an interview and one for understanding the process. Here’s the code:

  • Book.class
public class Book implements BeanNameAware.BeanFactoryAware.ApplicationContextAware.InitializingBean.DisposableBean {

    private String bookName;
    public Book(a){
        System.out.println("Book Initializing ");
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Book.setBeanFactory invoke");
    }

    public void setBeanName(String name) {
        System.out.println("Book.setBeanName invoke");
    }

    public void destroy(a) throws Exception {
        System.out.println("Book.destory invoke");
    }

    public void afterPropertiesSet(a) throws Exception {
        System.out.println("Book.afterPropertiesSet invoke");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Book.setApplicationContext invoke");
    }

    public String getBookName(a) {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
        System.out.println("setBookName: Book name has set.");
    }

    public void myPostConstruct(a){
        System.out.println("Book.myPostConstruct invoke");
    }

     // Customize the initialization method
    @PostConstruct
    public void springPostConstruct(a){
        System.out.println("@PostConstruct");
    }

    public void myPreDestory(a){
        System.out.println("Book.myPreDestory invoke");
        System.out.println("---------------destroy-----------------");
    }

    // Customize the destruction method
    @PreDestroy
    public void springPreDestory(a){
        System.out.println("@PreDestory");
    }

    @Override
    protected void finalize(a) throws Throwable {
        System.out.println("------inside finalize-----"); }}Copy the code
  • Customize MyBeanPostProcessor to implement BeanPostProcessor:
public class MyBeanPostProcessor implements BeanPostProcessor {

    // The container loads some other beans and calls the pre-initialization and post-initialization methods
    // Focus only on the life cycle of the book(bean)
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Book){
            System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Book){
            System.out.println("MyBeanPostProcessor.postProcessAfterInitialization");
        }
        returnbean; }}Copy the code
  • Create a new bean-lifecycle. XML file in the Resources directory
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  	<! -- Scan bean -->
    <context:component-scan base-package="com.bean.lifecycle"/>
  
    <! Implement user-defined initialization and destruction methods -->
    <bean id="book" class="com.bean.lifecycle.Book" init-method="myPostConstruct" destroy-method="myPreDestory">
      	<! Inject bean property name -->
        <property name="bookName" value="thingking in java" />
    </bean>

  	<! -- Introducing custom BeanPostProcessor-->
    <bean class="com.bean.lifecycle.MyBeanPostProcessor"/>

</beans>
Copy the code
  • Make a start class test, new SpringBeanLifecycleApplication
public class SpringBeanLifecycleApplication {

    public static void main(String[] args) throws InterruptedException {
        // The Bean lifecycle loading process for the interview
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
        Book book = (Book)context.getBean("book");
        System.out.println("Book name = "+ book.getBookName()); ((ClassPathXmlApplicationContext) context).destroy(); }}Copy the code

Start the test and the output is as follows:

Book Initializing setBookName: Book name has set. Book.setBeanName invoke Book.setBeanFactory invoke Book.setApplicationContext invoke MyBeanPostProcessor.postProcessBeforeInitialization @PostConstruct Book.afterPropertiesSet invoke Book.myPostConstruct invoke MyBeanPostProcessor.postProcessAfterInitialization Book name = thingking in java

@PreDestory Book.destory invoke Book.myPreDestory invoke —————destroy—————–

  • To verify the Bean’s full life cycle, you need to create a new SubBookClass that inherits the Book class
public class SubBookClass extends Book implements BeanClassLoaderAware.EnvironmentAware.EmbeddedValueResolverAware.ResourceLoaderAware.ApplicationEventPublisherAware.MessageSourceAware{

    private String bookSystem;

    public String getBookSystem(a) {
        return bookSystem;
    }

    public void setBookSystem(String bookSystem) {
        System.out.println("Set BookSystem property values");
        this.bookSystem = bookSystem;
    }

    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("SubBookClass. SetBeanClassLoader () method is called the");
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("SubBookClass. SetApplicationEventPublisher () method is called the");
    }

    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("SubBookClass. SetEmbeddedValueResolver () method is called the");
    }

    public void setEnvironment(Environment environment) {
        System.out.println("SubBookClass. SetEnvironment () method is called the");
    }

    public void setMessageSource(MessageSource messageSource) {
        System.out.println("SubBookClass. SetMessageSource () method is called the");
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("SubBookClass. SetResourceLoader () method is called the"); }}Copy the code

The SubBookClass class above is complementary to Book.

  • Create a new SubBean-Lifecycle. XML and inject the SubBookClass
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <bean id="bookClass" class="com.bean.lifecycle.SubBookClass" init-method="myPostConstruct" destroy-method="myPreDestory">
        <property name="bookSystem" value="Java System" />
    </bean>

    <bean class="com.bean.lifecycle.MyBeanPostProcessor"/>

</beans>
Copy the code
  • Complete SpringBeanLifecycleApplication as follows:
public class SpringBeanLifecycleApplication {

    public static void main(String[] args) throws InterruptedException {
        // The Bean lifecycle loading process for the interview
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
        Book book = (Book)context.getBean("book");
        System.out.println("Book name = " + book.getBookName());
        ((ClassPathXmlApplicationContext) context).destroy();

        // The complete loading process, of course, the more you know the better
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SubBean-Lifecycle.xml");
        SubBookClass subBookClass = (SubBookClass) applicationContext.getBean("bookClass");
        System.out.println("BookSystemName = "+ subBookClass.getBookSystem()); ((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook(); }}Copy the code

Output the full result:

Book Initializing setBookName: Book name has set. Book.setBeanName invoke Book.setBeanFactory invoke Book.setApplicationContext invoke MyBeanPostProcessor.postProcessBeforeInitialization @PostConstruct Book.afterPropertiesSet invoke Book.myPostConstruct invoke MyBeanPostProcessor.postProcessAfterInitialization Book name = thingking in java @PreDestory Book.destory invoke Book.myPreDestory invoke —————destroy—————–

Book the Initializing setting BookSystem attribute values of the Book. SetBeanName invoke SubBookClass. SetBeanClassLoader () method is called a Book. The setBeanFactory Invoke SubBookClass. SetEnvironment () method is called the SubBookClass. SetEmbeddedValueResolver () method is called SubBookClass. SetResourceLoader () method is called the SubBookClass. SetApplicationEventPublisher () method is called SubBookClass. SetMessageSource () method is called a Book. The setApplicationContext invoke MyBeanPostProcessor.postProcessBeforeInitialization Book.afterPropertiesSet invoke Book.myPostConstruct invoke MyBeanPostProcessor.postProcessAfterInitialization BookSystemName = Java System Book.destory invoke Book.myPreDestory invoke —————destroy—————–

Postscript: This article is the conclusion I got from reading all kinds of books and searching information from the Internet, including some foreign websites, and recorded it, but I did not find itSpring Bean lifecycle (very detailed)This article InstantiationAwareBeanPostProcessorAdapter this class and factory rear processor interface method, know the bosses welcome advice. Thanks.

In addition, add my becomecXuan on wechat to join the One question of the day group, one interview question of the day to share, for more content, please see my Github,Be the bestJavaer

I have uploaded six PDFS by myself. After searching the public account of “Programmer Cxuan” on wechat, I reply to CXuan on the background and get all PDFS. These PDFS are as follows

Six PDF links