Welcome everyone to pay attention to my WeChat public number [old week chat architecture], the principle of Java back-end mainstream technology stack, source code analysis, architecture and various Internet high concurrency, high performance, high available solutions.

One, foreword

Today we are going to talk about the life cycle of Spring beans, which is a normal phenomenon that you should encounter frequently in your job interview. Because the life cycle of Spring beans is the most important concept besides the core concepts of IOC and AOP, it’s important to take care of that. Spring source code and more complex, followed by do not know where to go, not very easy to get ah. This is true, and online on a variety of posted process source code, for beginners is really a face meng, like the word all understand, but even together do not know the meaning of the, too around.

In this article, Lao Zhou tried to make it easy to understand, so that more friends could easily understand the life cycle of Spring Bean, and have the idea of continuing to study it. Then the purpose of my writing this article will be achieved.

Before we look at the Spring Bean life cycle, let’s look at two concepts:

1.1 What is a Bean

Let’s take a look at the official documentation for the Spring Framework:

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.

In short, beans are objects that are instantiated, assembled, and managed by the Spring IOC container.

1.2 What is the Spring Bean Life Cycle

With normal Java objects, the object is created when new, and then the object can be used. Once the object is no longer in use, Java does garbage collection automatically.

The object in Spring is a bean. Beans are not much different from ordinary Java objects, except that Spring no longer uses the new object itself. Instead, the IOC container helps us instantiate the object and manage it. IoC is all about coupling between objects, and the life cycle of Spring beans is completely controlled by the container.

The Spring Bean life cycle

It is important to note that when we talk about the life cycle of Spring beans, we mainly refer to Singleton beans. In the case of Prototype beans, Spring does not manage the life cycle after they are created and handed over to the consumer.

Let’s also review the scope of beans in Spring.

  • singleton: A unique bean instance. Beans in Spring are singletons by default.
  • prototype: A new bean instance is created on each request.
  • request: Each HTTP request generates a new bean that is valid only within the current HTTP request.
  • sessionEach HTTP request results in a new bean that is only valid for the current HTTP Session.
  • global-session: Global Session scope, which only makes sense in portlet-based Web applications, is missing for Spring5. Portlets are small Java Web plug-ins that generate fragments of semantic code (for example, HTML). They are based on portlet containers and can handle HTTP requests like servlets. However, unlike servlets, each portlet has a different session.

We know that for ordinary Java objects, their life cycle is:

  • instantiation
  • The object is collected through the garbage collection mechanism when it is no longer in use

For the Spring Bean lifecycle:

  • Instantiate the Instantiation
  • Property assignment Populate
  • Initialize the Initialization
  • Destruction of Destruction

Instantiation -> attribute assignment -> initialization -> destruction

With only four steps, doesn’t it feel easy to disassemble? Unlike other people who write directly all kinds of BeanPostProcessor, BeanFactoryPostProcessor all into the process, not to mention the readers look too big, you may write a short time to remember the process, at a time, you may not know what you wrote.

Lao zhou was supposed to create process through Bean entrance AbstractApplicationContext# refresh () method of finishBeanFactoryInitialization (the beanFactory) take you to the source code, Think about it or not into too much code in, directly to the final main logic.

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) {// InstanceWrapper = this.createBeanInstance(beanName, MBD, args); }... Object exposedObject = bean; Try {// This. PopulateBean (beanName, MBD, instanceWrapper); // ExposeObject = this.initializeBean(BeannName, ExposeObject, MBD); // ExposeObject = this.initializeBean(BeannName, ExposeObject, MBD); } catch (Throwable var18) { ... }... }

As for destruction, is invoked when the container close, see ConfigurableApplicationContext# close ()

Isn’t that refreshing? As for BeanPostProcessor, BeanFactoryPostProcessor, and other classes, Mr. Zhou saw them as just a series of extension points to the four steps of the main process.

Extension points for the life cycle of Spring beans

There are so many extension points in the life cycle of Spring beans that it is impossible to list them all here, just the core extension points. This is why Spring extensibility works so well, opening up a lot of openings to make a feature as cohesive and loosely coupled as possible, and allowing users to use whatever functionality they want instead of just having one big, all-in-one thing.

3.1 Method of the Bean itself

For example, the constructor, getter/setter, init-method and destory-method are the four stages: instantiation -> attribute assignment -> initialization -> destruction. For example, the constructor, getter/setter, init-method and destory-method are the four stages: instantiation -> attribute assignment -> initialization -> destruction



3.2 Container-level methods (BeanPostProcessor series of interfaces)

Mainly after the handler method, such as the image below InstantiationAwareBeanPostProcessor, BeanPostProcessor interface methods. The implementation classes for these interfaces are bean-independent and are registered with the Spring container. These post-handlers come into play when the Spring container creates any Bean.



3.2.1 InstantiationAwareBeanPostProcessor source analysis

We found InstantiationAwareBeanPostProcessor search source is inherited BeanPostProcessor



  • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiationCall the point

Object postProcessBeforeInstantiation(Class<? > beanClass, String beanName)


If the return value is not null, then the subsequent Bean creation process (instantiation, initialization afterProperties) will not be executed and the returned shortcut Bean will be used directly. The normal order of execution is as follows:


The postProcessBeforeInstantiation InstantiationAwareBeanPostProcessor interface, call before instantiation.


The postProcessAfterInitialization BeanPostProcessor interface, call after instantiation.









Anyhow, postProcessBeforeInstantiation before doCreateBean calls, call before bean instantiation, English source annotation explains the return value of this method will replace the original beans as an agent, This is the key to implementing features such as AOP.

  • InstantiationAwareBeanPostProcessor#postProcessAfterInstantiationCall the point

boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException


Normally called after instantiation and before executing PopulateBean


The return value: If false is returned with the specified bean, then subsequent property populations and property dependency injection will not be performed. And the subsequent postProcessPropertyValues would not perform, but initialization and BeanPostProcessor will still be executed.

public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)


Called after the instantiation, before the method applyPropertyValues


Return value: If NULL is returned, subsequent attribute padding, such as dependency injection, will not be performed. If additional attributes are added to the returned PVS, then subsequent attribute padding will be performed for the corresponding class.


PVS: PropertyValues object is used to encapsulate the object of the specified class. Simply put, it is a collection of propertyValues, which is equivalent to storing the properties and values of the class in the form of key-value.


Pds: array of propertyDescriptor objects. PropertyDescriptor is equivalent to storing properties of the class, but you can call set and get the values of the corresponding properties.



3.2.2 BeanPostProcessor source code analysis

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean



Enter the initialization interface:



Let’s start with

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

  • So first we get all of the post-processors that getBeanPostProcessors() have.
  • The methods of the postprocessor are called in turn in the for loopprocessor.postProcessBeforeInitialization(result, beanName);
  • Enter the postProcessBeforeInitialization method

org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization

Enter invokeAwareInterfaces (bean); Method, the current bean implements the ApplicationContextAware interface.

  • ApplicationContextAwareProcessor#postProcessBeforeInitializationIf the bean is Aware, then the bean factory can import the relevant context into the container. The purpose is that the bean instance can get the relevant context. If the bean is not Aware, then call the bean factoryinvokeAwareInterfaces(bean), the context in which the relevant interface is added to the container.

3.3 Post-factory processor methods (BeanFactoryProcessor series of interfaces)

Including AspectJWeavingEnabler, CustomAutowireConfigurer, ConfigurationClassPostProcessor, etc. These are the BeanFactoryPostProcessors already implemented in the Spring framework to implement certain functions.

We know that the Spring IoC container initialization of the key links in the org. Springframework. Context. Support. AbstractApplicationContext# refresh method, The main process for container creation is in this method, and this method is really important!!

Methods for factory after processor Lao zhou directly take you to see here invokeBeanFactoryPostProcessors (the beanFactory); Method, which handles the Bean of the BeanFactoryPostProcessor interface. The call method is as follows:



Follow on to the most important method, the code is long, but the logic is good.

Spring BeanFactoryPostProcessor: all the father of the BeanFactory interface BeanDefinitionRegistryPostProcessor: implements the spring BeanFactoryPostProcessor interface interface



Process description:

  • Call BeanDefinitionRegistryPostProcessor# postProcessBeanDefinitionRegistry (registry) method. Parameter beanFactoryPostProcessors incoming priority. Then get the container registered beans, for these beans as PriorityOrdered interface, Ordered interface, no Ordered interface instance are processed respectively.
  • Call the BeanFactoryPostProcessor# PostProcessBeanFactory (BeanFactory) method. Note: BeanDefinitionRegistryPostProcessor belongs to spring BeanFactoryPostProcessor interface. Processing belongs to the first BeanDefinitionRegistryPostProcessor interface instance postProcessBeanFactory (the beanFactory) method, and get registered vessel. These beans are processed as PriorityOrdered interface, Ordered interface, and unordered interface instance respectively.

3.4 Bean-level life cycle methods

This can be interpreted as methods of the Bean class that implement the interface directly, such as BeannameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DispenableBean, etc., These methods are only valid for the current Bean.

3.4.1 Interface of type AWARE

The purpose of an Aware interface is to allow us to take some of the resources in the Spring container. The name before Aware is what you can get. For example, BeanNameAware can get BeanName, and so on. Note when to call: All Aware methods are called before the initialization phase.

There are many Aware interfaces, and here is also a way to help you remember them by classification. The Aware interfaces can be divided into two groups, as explained in the source code analysis below. The following order is also the order of execution of the Aware interface. The interface that can be known by name is not explained.

Aware Group1

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware

Aware Group2

  • EnvironmentAware
  • EmbeddedValueResolverAware

    This may not be known by many people, but the implementation of this interface can get the Spring EL parser, the user’s custom annotations need to support SPEL expressions can be used, very convenient.
  • ApplicationContextAware(ResourceLoaderAware/ApplicationEventPublisherAware/MessageSourceAware)

    These interfaces can be a bit confusing, but in fact they can be remembered together, and the return value is essentially the current ApplicationContext object, because ApplicationContext is a composite interface, as follows:

Aware call timing source analysis



As you can see, not all Aware interfaces are invoked in the same way. Beans of xx Aware are called directly in your code, is Aware of ApplicationContext through BeanPostProcessor# postProcessBeforeInitialization () implementation. Interested can look at our ApplicationContextAwareProcessor this class’s source code, is whether the current create Bean implements Aware of related methods, if implemented will call the callback method transfer resources to a Bean.

The invocation timing of the BeanPostProcessor can also be represented here, surrounding the invokeInitMethods method, which means execution before and after the initialization phase.

As for the order in which the Aware interface is executed, you just need to remember that the first group is executed before the second.

3.4.2 Lifecycle Interface

The remaining two lifecycle interfaces are very simple, instantiation and property assignment are done by Spring, and we can implement the initialization and destruction lifecycle phases on our own.

  • InitializingBeanCorresponding to the initialization phase of the lifecycle, in the above sourceinvokeInitMethods(beanName, wrappedBean, mbd);Method.

One thing to note is that since the Aware methods are executed before the initializer methods, you can feel free to use the resources from the Aware interface in the initializer methods, which is a common way to customize extensions to Spring. In addition to the implementation of the InitializingBean interface, you can specify the initialization method through annotations or XML configuration. There is no need to remember the order in which these methods are defined. Because all of these methods correspond to the same lifecycle, but are implemented in different ways, we usually only use one of them.

  • DisposableBeanSimilar to the InitializingBean, corresponding to the destruction phase of the life cycle, withConfigurableApplicationContext#close()Method as the entry point, implemented by looping through all the beans that implement the DisposableBean interface and calling their destroy() method, follow through the source code if you’re interested.

3.5 Spring Bean life cycle flowchart

IV. Description of commonly used interfaces

4.1 BeanNameAware

The interface has only one method, setBeanname (String Name), which retrieves the bean’s ID or name.

4.2 BeanFactoryAware

The interface has only one method, setBeanFactory(BeanFactory BeanFactory), which is used to get the BeanFactory in the current environment.

4.3 ApplicationContextAware

The interface has only one method, setApplicationContext(ApplicationContext ApplicationContext), which gets the ApplicationContext in the current environment.

4.4 InitializingBean

The interface has only one method afterPropertiesSet(), which is called after property injection is complete.

4.5 DisposableBean

The interface has only one method, destroy(), which is called when the container is destroyed and before the destroy-method specified by the user.

4.6 BeanPostProcessor

The interface has two methods:

  • postProcessBeforeInitialization(Object bean, String beanName)In:Before initializationCall this method
  • postProcessAfterInitialization(Object bean, String beanName)In:After initializingCall this method

As we know from the method signature, we can use the beanName to filter out the beans that we need to personalize.

4.7 InstantiationAwareBeanPostProcessor

This class is a subinterface of the BeanPostProcessor with three common methods:

  • postProcessBeforeInstantiation(Class beanClass, String beanName): in the beanBefore you instantiatecall
  • postProcessProperties(PropertyValues pvs, Object bean, String beanName): in the beanAfter instantiation, before setting propertiescall
  • postProcessAfterInstantiation(Class beanClass, String beanName): in the beanAfter the instantiationcall

Five, code demonstration

Create a class UserBean, let it implement several special interfaces, and at the interface implementation constructor, interface method breakpoints, respectively, observe the thread call stack, analyze the Bean object creation and management key point trigger timing.

5.1 the UserBean class

@Component public class UserBean implements InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware { private int id; private String name; public UserBean(int id, String name) { this.id = id; this.name = name; System.out.println("2. Call the constructor "); } public int getId() { return id; } public void setId(int id) { this.id = id; System.out.println("5. Attribute Injection ID "); } public String getName() { return name; } public void setName(String name) { this.name = name; System.out.println("5. Attribute Injection Name "); } @Override public void setBeanName(String name) { System.out.println("6. Call BeanNameAware. SetBeanName () method "); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { UserBean userBean = (UserBean) applicationContext.getBean("userBean"); System.out.println(userBean); System. The out. Println (" 7. Call BeanNameAware. SetBeanName () method "); } @Override public void afterPropertiesSet() throws Exception { System.out.println("9. Call InitializingBean. AfterPropertiesSet () method "); } public void myInit() { System.out.println("10. Call the init-method method "); } @Override public void destroy() throws Exception { System.out.println("12. Invoke the disposableBean.destroy () method "); } public void myDestroy() { System.out.println("13. Call the destroy-method method "); } @Override public String toString() { return "UserBean{" + "id=" + id + ", name='" + name + '\'' + '}'; }}

5.2 InstantiationAwareBeanPostProcessor interface implementation class

@Component public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override  public Object postProcessBeforeInstantiation(Class<? > beanClass, String beanName) throws BeansException { if ("userBean".equals(beanName)) { System.out.println("1. Call InstantiationAwareBeanPostProcessor. PostProcessBeforeInstantiation () method "); } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if ("userBean".equals(beanName)) { UserBean userBean = (UserBean) bean; System. The out. Println (" 3. Call InstantiationAwareBeanPostProcessor. PostProcessAfterInstantiation () method "); System.out.println(userBean); } return true; } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { if ("userBean".equals(beanName)) { System.out.println("4. Call InstantiationAwareBeanPostProcessor. PostProcessProperties () method "); } return null; }}

5.3 BeanPostProcessor interface implementation class

@Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("userBean".equals(beanName)) { System.out.println("8. Call BeanPostProcessor. PostProcessBeforeInitialization () method "); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("userBean".equals(beanName)) { System.out.println("11. Call BeanPostProcessor. PostProcessAfterInitialization () method "); } return bean; }}

5.4 BeanFactoryPostProcessor interface implementation class

@Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("0. Call spring BeanFactoryPostProcessor. PostProcessBeanFactory () method "); }}

5.5 applicationContext. XML

<? The 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 https://www.springframework.org/schema/beans/spring-beans.xsd "> <bean class="com.riemann.test.MyInstantiationAwareBeanPostProcessor" /> <bean id="userBean" class="com.riemann.test.UserBean" init-method="myInit" destroy-method="myDestroy"> <! Type ="int"> <value>1</value> </constructor- > </constructor- > </constructor- > </constructor-arg index="1" Type =" java.lang.string "> <value> </value> </constructor-arg> <! -- setter method inject --> <property name="id" value="2"/> <property name="name" value=" Riemann "/> </bean> <bean class="com.riemann.test.MyBeanPostProcessor" /> <bean class="com.riemann.test.MyBeanFactoryPostProcessor" /> </beans>

5.6 the test class

public class BeanLifeCycleTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); UserBean user = (UserBean) applicationContext.getBean("userBean"); ((AbstractApplicationContext) applicationContext).close(); }}

5.7 Console result printing