“This is the 17th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

1. Introduction

Protected Object createBean(String beanName, RootBeanDefinition MBD, @Nullable Object[] args) throws BeanCreationException method. This method creates a bean column, populates the bean instance, and executes the bean’s post-processors.

2. createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

Let’s follow the source code to see the detailed processHere we first define an mbdToUse variable to be used as a copy of MBD

2.1 resolveBeanClass (MBD, beanName);

This method parses the type of the beanName and returns it. Such as: com. LCX. Serviece. TestServiceImpl

1. Check whether mbd.beanClass belongs to mbD. beanClass. If mbD. beanClass belongs to mbD. beanClass. Check whether the current system security policy manager is null. If it is not null, give the code inside a privilege to bypass the permission check. 3. The core here is to call doResolveBeanClass(MBD, typesToMatch)

2.1.1 doResolveBeanClass (MBD, typesToMatch)

private Class<? > doResolveBeanClass(RootBeanDefinition mbd, Class<? >... TypesToMatch) throws ClassNotFoundException {// Get the current container's ClassLoader beanClassLoader = getBeanClassLoader(); // create a copy of ClassLoader dynamicLoader = beanClassLoader; Boolean freshResolve = false; // The name of the configured bean class needs to be reloaded by dynameicLoader. // When typesToMatch is not null if (! ObjectUtils.isEmpty(typesToMatch)) { // When just doing type checks (i.e. not creating an actual instance yet), // use the specified temporary class loader (e.g. in a weaving scenario)  = getTempClassLoader(); if (tempClassLoader ! DynamicLoader = tempClassLoader; dynamicLoader = tempClassLoader; dynamicLoader = tempClassLoader; freshResolve = true; If (tempClassLoader instanceof DecoratingClassLoader) {// Type conversion DecoratingClassLoader DCL = (DecoratingClassLoader) tempClassLoader; // Exclude typesToMatch from DCL for (Class<? > typeToMatch : typesToMatch) { dcl.excludeClass(typeToMatch.getName()); }}}} // returns the className of the current bean. See figure 2.1 for the source code. String className = mbd.getbeanclassname (); if (className ! = null) {// Evaluate the className contained in BeanDefinition, parse it if className is a resolvable expression, Otherwise directly return to the source as shown in figure 2.2 the Object evaluated = evaluateBeanDefinitionString (className, MBD); // If the two are different, className is a parsed string. if (! ClassName. Equals (evaluated)) {// A dynamically resolved expression, supported as of 4.2... Evaluated if (evaluated instanceof Class) {// Return (Class<? >) evaluated; If evaluated instanceof String) {// If evaluated instanceof String, evaluate it to className. ClassName = (String) evaluated; freshResolve = true; } else { throw new IllegalStateException("Invalid class name expression result: " + evaluated); Resolving against a temporary if (freshResolve) {// When resolving against a temporary if freshResolve == true class loader, exit early in order // to avoid storing the resolved Class in the bean definition. if (dynamicLoader ! Return dynamicLoader.loadClass(className); return dynamicLoader.loadclass (className); } catch (ClassNotFoundException ex) { if (logger.isTraceEnabled()) { logger.trace("Could not load class [" + className +  "] from " + dynamicLoader + ": " + ex); Return classutils. forName(className, dynamicLoader); } } // Resolve regularly, caching the result in the BeanDefinition... // The BeanDefinition class is parsed by the beanClassLoader, and the result is saved in the beanClass. Return mbd.resolveBeanClass(beanClassLoader); }Copy the code

Figure 2.1:As you can see, it first fetches the beanClass of the beanDefinition of the current bean, and returns it by calling its getName() method if it is an instance of Class, otherwise it returns it as a string. Here if beanClass is null then callmbd.resolveBeanClass(beanClassLoader)It will cache the result in the beanClass.

Figure 2.2:That’s the main thingParsing SPEL expressionsI have put an article for it, if you are interested, you can have a look.

Figure 2.3: This is mainly about loading the class (parent delegate mechanism)

  • First, it will check whether the class is loaded. If not, it will get the parent class loader. When the parent class loader is not null, it will call the loading method of the parent class loader. If it still doesn’t load, load it down one layer at a time.
  • If you need to parse the class after loading, parse and return

So this is important and we can talk a little bit more about class loaders when we have time.

Classutils.forname (className, dynamicLoader) : This method is used by Spring to replace class.forname () and load classes, but I’ll talk more about it later.

2.2

MBD’s beanClass is not of Class type, and MBD’s beanClass is not null. A copy of MBD will be cloned, replacing MBD’s subsequent operations to set the beanClass of mbdToUse.

2.3 mbdToUse. PrepareMethodOverrides ()

The main function of this method is to verify the preparation method rewrite, source code is as follows:

  1. First check whether the current beanDefinition methodOverrides is null
  2. If not null, get all methodOverride traversal of the current methodOverrides and call the prepareMethodOverride () method.
  3. PrepareMethodOverride (), source code as follows:
    • First statistics specified number match the method name in the class of methods, including the public methods, because already came in, so it matches the number method for 0, when it is 0 Throw an exception, when it is 1, shows that it is a method that rewriting may not include overloading, marked here will cover not overloading, in order to avoid the overhead of arg type checking.
    • GetMethodCountForName method:

      1. Now get all of clazz’s methods, take their names and methodName and if they’re the same then count++;
      2. Get all the interfaces implemented by Clazz, iterate over each interface, recursively call the current method, count = count+ the return value of the recursion
      3. Get clazz’s parent class, and then recursively call the current method, count = count+ the recursive return value
      4. Returns the count

2.4 resolveBeforeInstantiation (beanName, mbdToUse)

Here is what it does:Give BeanPostProcessors the opportunity to return a proxy instead of the target bean instance.Return the proxy if it is available, otherwise call the following doCreateBean(beanName, mbdToUse, args)

  • First determine whether the default false has been resolved
  • Mbd.issynthetic (): returns whether the current bean definition isSynthetic
  • HasInstantiationAwareBeanPostProcessors () : returns whether this factory has the instantiation WareBeanPostProcessor
  • The determineTargetType method is used to determine the target type of the bean definition.
  • If targetType not null when the applyBeanPostProcessorsBeforeInstantiation get bean (targetType, beanName), If the bean is not null then call applyBeanPostProcessorsAfterInitialization (bean, beanName).
  • If the bean is not null shows that he has been parsed, MBD. BeforeInstantiationResolved set to true. Return result directly.

1. applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)

  • Take the beanPostProcessors of the current container and walk through them.
  • judge If the BeanPostProcessor InstantiationAwareBeanPostProcessor instance, call postProcessBeforeInstantiation method.
  • PostProcessBeforeInstantiation methods: used to call before Bean instantiation. If the value returned by this method is not empty, the object is returned directly to the Spring container as the bean that was created.

2. applyBeanPostProcessorsAfterInitialization(bean, beanName)

  • Let’s go through the beanPostProcessors of the current container
  • Traverse perform their postProcessAfterInitialization method. If null is returned, result is returned; otherwise, current is assigned to result.
  • PostProcessAfterInitialization method: Call after the bean instantiation, usually used to bean set attribute information, if the return value is not null, always call back BeanPostProcessor# postProcessAfterInitialization, once returns null, return to the result directly

2.5 doCreateBean(beanName, mbdToUse, args);

Performed in front of the four steps, still not return, it invokes the method, its main effect: actually creating the specified bean code, but before that, it needs to be done beforehand to create processing Such as: check {@ code postProcessBeforeInstantiation} callback. This method is designed to go into the nuts and bolts of creating beans, which I’ll cover separately later in this article.