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

As the book continues, it’s time for the more complex section of constructing beans. Let’s review the previous section:

Create your own

RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // This step will check if it is abstract BD. If it is abstract BD, it will not be able to construct a bean. checkMergedBeanDefinition(mbd, beanName, args);Copy the code

Now that you’ve got the BD, it’s time to formally go through the process of creating the bean.

Step 1: Ensure that the dependent beans are created

The corresponding code is as follows:

String[] dependsOn = mbd.getDependsOn(); if (dependsOn ! = null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); Try {// we recurse getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); }}}Copy the code

A dependency is a related class annotated by @dependson (), not an attribute defined in the class.

  • Circular depends-on: @dependson cannot be Circular dependent.

    • So here’s another problem: If the interdependence of triangular cycles occurs, it cannot be judged directly, but also needs to check whether there is a cyclic dependence relationship. Therefore, isDependent(beanName, DEP) method makes this judgment to check whether there is a cyclic dependence problem on the dependent linked list nodes.

      RegisterDependentBean (deP, beanName);

      This will store the dependency information in a map.

Note that an @dependson has a higher priority than an @autowired DependsOn, which must be initialized.

After recording, the dependent bean is created: getBean(DEP);

Step 2: Distinguish scope

Recall that there are several steps to creating a bean?

  • Class loading, instantiation, pre and post process, property injection

And beans are divided into: prototype beans and singleton beans.

There are three of them.

  • Singleton:

    This part goes here:

    if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; }}); beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }Copy the code
  • Prototype:

     else if (mbd.isPrototype()) {
        // It's a prototype -> create a new instance.
        Object prototypeInstance = null;
        try {
           beforePrototypeCreation(beanName);
           prototypeInstance = createBean(beanName, mbd, args);
        }
        finally {
           afterPrototypeCreation(beanName);
        }
        beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
     }
    Copy the code
  • Other scopes (from SpringMVC, request,session, etc.) :

    else { String scopeName = mbd.getScope(); if (! Stringutils.haslength (scopeName)) {throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'"); } Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); }}); beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new ScopeNotActiveException(beanName, scopeName, ex); }}Copy the code

    The scope here actually means the same as the singleton, except that the cached information will be stored in the scope, and the corresponding beans in the scope are also singleton, but singleton is global. Here is scope.

Here the key code is the same:

// Record the prototype bean and other scopes that are now being created, use map to store beforePrototypeCreation(beanName); createBean(beanName, mbd, args); // afterPrototypeCreation(beanName) is stored in map. getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);Copy the code

The difference is that you create a prototype and try to get it.

The key here is createBean: Create the bean object.