preface

When you’re ready to review the life cycle of beans in Spring, and you start looking online, there’s a good chance you’ll see something like this:

image-20200707094637369

Regardless of whether this map is comprehensive or not, but say this map, do you memorize and forget, forget and back?

Is it because you don’t understand why these steps are needed or why you need to do them in this order

After reading the complete IOC and AOP source code, I hope to talk about my Spring Bean life cycle through this article, to help you understand the memory of the whole process, rather than rote memorization!

Basic knowledge supplement

So-called understanding is also built on the basis of certain knowledge reserves, so here to supplement a few basic concepts first

The three phases of Bean creation

Spring creates a Bean in three steps

  • Instantiate, you can think of it as new an object
  • Property injection, which can be interpreted as calling setter methods to complete property injection
  • Initialization, you can configure some of the initialization methods according to Spring rules (for example,@PostConstructAnnotations)

The concept of life cycle

The Bean life cycle refers to the process interspersed between the preceding three steps by the post-processor BeanPostprocessor

Analysis of the rear processor

Categorize by implementation interface

  1. Directly implementedBeanPostProcessorinterface

The simplest post-processor, which directly implements the BeanPostProcessor interface, can only be executed before and after initialization

public interface BeanPostProcessor {
    
 // The method executed before initialization
 @Nullable
 default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 return bean;  }   // The method executed after initialization  default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  return bean;  }  } Copy the code
  1. Directly implementedInstantiationAwareBeanPostProcessorinterface

A layer of extensions to the first post-processing can be performed before and after the Bean’s instantiation phase

// Inherits BeanPostProcessor, which provides two additional methods for execution in the phases before and after instantiation
The interface also provides a property injection method, since instantiation is immediately followed by property injection
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
 
    // execute before instantiation
 default Object postProcessBeforeInstantiation(Class
             beanClass, String beanName) throws BeansException {  return null;  }   // instantiate after  default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {  return true;  }   // Attribute injection  default PropertyValues postProcessPropertyValues(  PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {   return pvs;  } } Copy the code
  1. A dedicated post-processor inside Spring

Some people think that the third type of post-processor must be used to execute before and after the property injection. All I can say is, dude, that’s naive. Look at the picture below

image-20200707163736980

In this case, isn’t it a bit redundant to provide two methods for the property injection phase? The third post-processor is actually designed specifically by Spring for its own use

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
 
    // Guess the type of the bean, for example in the property injection phase we need to know which beans match the dependent type
    @Nullable
    defaultClass<? > predictBeanType(Class<? > beanClass, String beanName)throws BeansException {
 return null;  }   We need to specify which constructor to use when instantiating the object  @Nullable  defaultConstructor<? >[] determineCandidateConstructors(Class<? > beanClass, String beanName) throws BeansException {   return null;  }   // Get a pre-exposed object to resolve loop dependencies  default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {  return bean;  }  } Copy the code

We usually don’t think about this kind of post-processor execution when we’re exploring the life cycle

Details about the life cycle

With the above concepts in mind, let’s take a look at this diagram

image-20200707094637369

At least now this diagram is missing the execution flow of the post-instantiation processor before and after instantiation, right?

Add on this, we take a look at, properties after injection and then is the initialization stage, before the start of the initialization phase should call BeanPostProcessor initialization method (postProcessBeforeInitialization), Then calls a custom initialization method, and finally call postProcessAfterInitialization, this is no problem, but why even before the initial call Aware interface method, may say, if you see the source code source code is written, so others is so of the design, But why design it this way? When we look at the source code at a certain stage, we should not only stop at the “what” stage, but also think about the “why”, which will help you understand the framework better

So why should the Aware interface be executed before initialization?

This is done because initialization may depend on the state provided by the Aware interface, as in the following example

@Component
public class A implements InitializingBean.ApplicationContextAware {

    ApplicationContext applicationContext;

 @Override  public void afterPropertiesSet(a) throws Exception {  // The initialization method uses the ApplicationContext provided by ApplicationContextAware  System.out.println(applicationContext);  }   @Override  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  this.applicationContext = applicationContext;  } } Copy the code

In this case, the Aware interface must be executed before initialization.

In addition, when discussing Bean initialization often encounter the following problems, @ PostConstruct, afterPropertiesSet init – method with XML configuration method of execution order.

Please note that @ PostConstruct actually postProcessBeforeInitialization methods in the treatment of, strictly speaking, it does not belong to the method called initialization phase, so this method is the first to call

Next, is it more expensive to call the afterPropertiesSet method or to perform the initialization method named in the configuration file? Let’s do this in pseudocode

// afterPropertiesSet
((InitializingBean) bean).afterPropertiesSet()
    
// reflection calls init-method
// Step 1: Find the method
Method method = class.getMethod(methodName) // Step 2: reflection calls this methodmethod.invoke(bean.null) Copy the code

By comparison, the first method is definitely more efficient than the second one, where one only makes one method call and the other calls two reflections.

Therefore, afterPropertiesSet takes precedence over XML configuration

Therefore, the execution sequence of these three methods is:

  1. @PostConstructAnnotation annotation method
  2. To achieve theInitializingBeanInterface after the copyafterPropertiesSetmethods
  3. Custom initialization methods in XML

At the completion of initialization, there is nothing to say, the final call postProcessAfterInitialization, whole Bean lifecycle to the end

conclusion

The main purpose of this article is to help you better understand the entire Bean life cycle, but understanding is based on a certain amount of knowledge stored

You should have at least a general understanding of Bean postprocessor and Bean creation, so you can sort out some of the details in this article

For example, why is the Aware interface executed before the initialization phase? Why do the three initialization methods press

@postconstruct, afterPropertiesSet, the initialization methods defined in XML are executed in this order.

This article will be my last article on IOC and AOP in the whole Spring. After this, I plan to do a Spring transaction topic, which is expected to be 6 to 7 articles. After the transaction, the study of the whole Spring source code will be over! It was supposed to take a year to finish, but since I recently left my job, I plan to finish the series full-time at home!

If this article helped you, give it a thumbs up! Also welcome to pay attention to my public number, wechat search: Programmer DMZ, or scan the two-dimensional code below, follow me to learn Java seriously, do a solid coder.

The public,

My name is DMZ, a small rookie crawling on the learning road!

This article is formatted using MDNICE