Spring source code (14) creation process of Spring Bean

🚀 High quality resource sharing 🚀

Learning route guidance (click to unlock)Knowledge orientationCrowd positioning
🧡 Python actual wechat ordering applet 🧡Progressive classThis course is the perfect combination of Python Flash + wechat applet. From project construction to Tencent cloud deployment and launch, it creates a full stack ordering system.
💛 Python quantitative trading practice 💛beginner Take you hand in hand to build an easy to expand, safer and more efficient quantitative trading system

So far, we know that Spring has five methods to create Bean objects, namely:

  • Create using the getObject method of FactoryBean
  • It is created using the postprocessbeforeinstance method of instantiaawarebeanpostprocessor, a sub interface of BeanPostProcessor
  • Set the Supplier property of BeanDefinition to create
  • Set the factory method of BeanDefinition to create
  • Create using the whole process: getBean -- > dogetbean -- > createbean -- > docreatebean reflection

As described in the previous 4, we will introduce the fifth one. We know that if you use reflection to create, you must know to use the constructor for instantiation, because the constructor can be used to set the parameters.

SmartInstantiationAwareBeanPostProcessor interface

As mentioned earlier, InstantiationAwareBeanPostProcessor is used to instantiate objects in advance, while SmartInstantiationAwareBeanPostProcessor is a sub interface of InstantiationAwareBeanPostProcessor. What is it used for?

Source code in createBeanInstance method:

// Omit code
// Specify that the constructor is from the BeanPostProcessor, and the corresponding is AutowiredAnnotationBeanPostProcessor
// It is a subclass of SmartInstantiationAwareBeanPostProcessor and is implemented using determineCandidateConstructors
// Parse constructor
Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  return autowireConstructor(beanName, mbd, ctors, args);
}
// Omit code


Click in:

protected Constructor[] determineConstructorsFromBeanPostProcessors(@Nullable Class beanClass, String beanName)
  throws BeansException {

  if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
        // Determine candidate constructors
        Constructor[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
        if (ctors != null) {
          return ctors;
        }
      }
    }
  }
  return null;
}

You can see that this interface is used to parse the constructor of BeanClass. The implementation class of SmartInstantiationAwareBeanPostProcessor, autowirediannotationbeanpostprocessor, is used to parse and determine the appropriate constructor, focusing on the @ Autowired annotation, as well as the @ Value annotation and @ Lookup annotation.

After the constructor is parsed, the autowireConstructor method is called for instantiation. A constructor resolver will be created during parsing. It is also used when parsing factoryMethod. This class uses the method of instantiateUsingFactoryMethod, and parsing factoryMethod is more complex. It is necessary to judge whether it is a static factory creation or an instance factory creation, The construction analysis of automatic assembly is relatively simple, which is solved by autowireConstructor method.

Finally, the construction method and parameters are resolved and instantiated:

// Instantiate using appropriate construction methods and construction parameters
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));

Instantiation:

private Object instantiate(
 String beanName, RootBeanDefinition mbd, Constructor constructorToUse, Object[] argsToUse) {

  try {
    // Cglibsubclassing instantiationstrategy is generally used to obtain the instantiation strategy
    InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
    if (System.getSecurityManager() != null) {
      return AccessController.doPrivileged((PrivilegedAction) () ->
 strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
 this.beanFactory.getAccessControlContext());
 }
 else {
 // Start instantiation
 return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
 }
 }
 catch (Throwable ex) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "Bean instantiation via constructor failed", ex);
 }
}

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
 final Constructor ctor, Object... args) {
 if (!bd.hasMethodOverrides()) {
 if (System.getSecurityManager() != null) {
 // use own privileged to change accessibility (when security is on)
 AccessController.doPrivileged((PrivilegedAction) () -> {
 ReflectionUtils.makeAccessible(ctor);
 return null;
 });
 }
 // Instantiation class, reflection call
 return BeanUtils.instantiateClass(ctor, args);
 }
 else {
 // If the method is overridden, the lookup method and replace method
 return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
 }
}

If none of the previous parses are to Bean, the parameterless constructor will be used for parsing:

// Omit code
// Preferred constructors for default construction?
// The preferred constructor is the default creation method, and the @ Primary annotation is used as the preferred object creation method
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
  return autowireConstructor(beanName, mbd, ctors, null);
}

// No special handling: simply use no-arg constructor.
// Call the parameterless constructor to instantiate the object
return instantiateBean(beanName, mbd);

Instantiate Bean:

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
  try {
    Object beanInstance;
    if (System.getSecurityManager() != null) {
      beanInstance = AccessController.doPrivileged(
        (PrivilegedAction) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
 getAccessControlContext());
 }
 else {
 // Instantiate the object and create it using reflection
 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
 }
 // Create a Bean wrapper
 BeanWrapper bw = new BeanWrapperImpl(beanInstance);
 // Initializes the wrapper for the Bean
 initBeanWrapper(bw);
 return bw;
 }
 catch (Throwable ex) {
 throw new BeanCreationException(
 mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
 }
}

Here we can see that the Bean is wrapped by using factoryMethod and autowireConstructor to resolve the constructor for instantiation or using parameterless constructor for instantiation. What's the role of this packaging?

Function of BeanWrapper

Let's first look at how the previous method creates BeanWrapper:

Factory method parsing, ConstructorResolver#instantiateUsingFactoryMethod method:

public BeanWrapper instantiateUsingFactoryMethod(
 String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
		// Create a Bean wrapper
		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);
		// factoryBean
		Object factoryBean;
		// factory class
		Class factoryClass;
		// Identifies whether the factory is static
		boolean isStatic;
        // Omit code
}  

Smartinstantiaawarebeanpostprocessor subclass AutowiredAnnotationBeanPostProcessor resolves the constructor, and then uses ConstructorResolver#autowireConstructor to execute:

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
 @Nullable Constructor[] chosenCtors, @Nullable Object[] explicitArgs) {
		// Create a wrapper
		BeanWrapperImpl bw = new BeanWrapperImpl();
		// Initialize wrapper
		this.beanFactory.initBeanWrapper(bw);
		// Constructor
		Constructor constructorToUse = null;
		// Construction parameters
		ArgumentsHolder argsHolderToUse = null;
		// Construction parameters to be used
		Object[] argsToUse = null;
		// If the explicit construction parameter is not empty, it is assigned to the construction parameter to be instantiated
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
        // Omit code
}

Finally, the conversion services ConversionService and PropertyEditorRegistry will be registered. One is used for property type conversion and the other is used for property value resolution:

protected void initBeanWrapper(BeanWrapper bw) {
  // Get the transformation service and put it in the wrapper of the bean
  bw.setConversionService(getConversionService());
  // Register custom attribute editor
  registerCustomEditors(bw);
}

In the previous article, I introduced how to use these two, and also customized the Attribute Editor and type conversion. You can go to see them if you need them:

https://blog.csdn.net/redwinter/p/16167214.html and https://blog.csdn.net/redwinter/p/16241328.html

Here, the instantiation of Bean is completed, and then look at the source code:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  throws BeanCreationException {

  // Instantiate the bean.
  BeanWrapper instanceWrapper = null;
  // Get the Bean object of FactoryBean from the cache
  if (mbd.isSingleton()) {
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  }
  if (instanceWrapper == null) {
    // Instantiate object
    instanceWrapper = createBeanInstance(beanName, mbd, args);
  }
  // Get Bean object from wrapper
  Object bean = instanceWrapper.getWrappedInstance();
  // Get Bean type from wrapper
  Class beanType = instanceWrapper.getWrappedClass();
  if (beanType != NullBean.class) {
    mbd.resolvedTargetType = beanType;
  }

  // Allow post-processors to modify the merged bean definition.
  synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
      try {
        // Merge Bean
        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      }
      catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "Post-processing of merged bean definition failed", ex);
      }
      mbd.postProcessed = true;
    }
  }
}

Click in:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName) {
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof MergedBeanDefinitionPostProcessor) {
      MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
      // Perform merge BeanDefinition
      bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    }
  }
}

You can see that there is an interface MergedBeanDefinitionPostProcessor, which is also a sub interface of BeanPostProcessor. What is it used for?

MergedBeanDefinitionPostProcessor interface

Click to find that the implementation classes of this interface are all related to annotations. The most important is the CommonAnnotationBeanPostProcessor implementation class. Two annotations are set in the constructor: @PostConstruct and @PreDestroy. One is called after initialization, and the other is called when the container is destroyed.

To be continued

Tags: Spring Back-end Flask computer

Posted by pspcrazy on Fri, 13 May 2022 23:05:36 +0300