Location>code7788 >text

An in-depth analysis of bean instantiation from the underlying source code

Popularity:466 ℃/2024-12-19 21:21:06

Overall life cycle process

The Spring container can manage the lifecycle of a singleton scope bean, where Spring knows exactly when the bean is created, when initialization is complete, and when it is destroyed.

For prototype-scoped beans, Spring is only responsible for creating them, and when the container creates an instance of the bean, the instance of the bean is handed over to the client code to manage, and the Spring containerWill no longer track its life cycleThe Spring container creates a new instance each time a client requests a prototype-scoped bean. Each time a client requests a prototype-scoped bean, the Spring container creates a new instance and does not care about the lifecycle of the beans that are configured for prototype scoping.

The point of understanding the Spring life cycle is thatYou can use a bean to perform certain actions at specific times during its lifetime., i.e., the point of expansion. There may be many such moments, but in general, some relevant operations are performed after the bean is initialized and before it is destroyed. For more information on the use of extension points, seethis article, you can read these two articles together.

The bean's post processors, BeanPostProcessors, also need to be processed before and after the initialization method is executed:

  1. existinvokeInitMethods rounding offapplyBeanPostProcessorsBeforeInitialization,applyBeanPostProcessorsAfterInitialization

  2. The post-processing is handled by the AOP [AnnotationAwareAspectJAutoProxyCreator], the InitDestoryAnnotationBeanPostProcessor which is responsible for the @PostConstruct after the construction and the @PreDestroy before the destruction.

  3. and through custom processors that implement the BeanPostProcessor interface

  • The overall flow of the bean lifecycle is as follows:
  1. Load Bean Definitions: Scan all xml configurations, annotations by loadBeanDefinitions to record the bean in beanDefinitionMap. That isInitialization process for IOC containers

  2. Bean instantiation: traversing the beanDefinitionMap to create the bean, and ultimately using the doGetBean method in getBean to call createBean to create the bean object.

    1. Constructing an object: The container performs object construction via createBeanInstance.

      1. Get the constructor (in most cases there is only one constructor)

        1. If there is only one constructor, it is used regardless of whether the constructor has an entry parameter or not.

        2. When there are multiple constructor methods

          1. Take the constructor with @Autowired first, but if multiple constructors have @Autowired it will report an error

          2. If there is no constructor with @Autowired, then look for the one with no entry; if multiple constructors are entered, that will also report an error

      2. Preparation parameters

        1. Lookup by class first

        2. If there is more than one instance of this class, then match the parameter names based on the

        3. Error if not found

      3. Constructed Objects: Instantiate directly with a parameterless constructor.

    2. Populate properties: The populateBean method assigns values to properties needed inside the bean, usually variables annotated with @Autowired; populated through a three-level caching mechanism, also known as dependency injection.

    3. Initialize Bean Object: Initialize populated instances by initializeBean

      1. Execute Aware: check if there are three Aware for the implementer:BeanNameAwareBeanClassLoaderAware, BeanFactoryAware; location information that allows instantiated objects to perceive their presence in the Spring container, creation information

      2. Before initialization: BeanPostProcessor, that is, take out all the post processor for bean processing, when there is a processor returns null, will no longer call the later processor processing.

      3. Initialization: afterPropertiesSet, init- method;

        1. Classes that implement the InitializingBean interface execute their afterPropertiesSet() method.

        2. Getting the initMethod method from a BeanDefinition

      4. After initialization: BeanPostProcessor,; get all the bean's post processors to execute.AOP is also done here

    4. Registration Destruction: Handles the registration of beans that implement the DisposableBean interface through reigsterDisposableBean.

      1. Whether the bean is eligible to be registered as a DisposableBean:

        1. Whether or not there is a destroyMethod.

        2. Whether or not there is a post processor that executes the destruction method.

      2. DisposableBeanAdapter: Extrapolates the destoryMethod.

      3. Complete Registration

  3. Add to singleton pool: Add the bean to the singleton pool of singleObjects via the addSingleton method.

  4. destroy (by melting or burning)

    1. Before destroying: if there is a method annotated @PreDestory, execute it.

    2. If you have a customized destruction post-processor, destroy the beans one by one by calling the destoryBean via the postProcessBeforeDestruction method.

    3. On destruction: execute destory method if destroyMethod is implemented

    4. Perform customer-defined destruction: call invokeCustomDestoryMethod to execute the customized destroyMethod method on the bean

      1. With this customized destruction it will execute

      2. Without customizing the destroyMethod method it goes to the close method.

      3. Without the close method, the shutdown method is executed.

      4. If none of them are available, none of them will be implemented, without prejudice.

Instantiation of Beans

BeanFactory defines the specification of the bean container , which contains the bean instance according to the bean name , Class type and parameters , etc. to get the bean instance .

// groundbeannames andClassType, etc. to getbeanan actual example
Object getBean(String name) throws BeansException;
Object getBean(String name, Class requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

IoC initialization, the final is the definition of the bean that BeanDefinition into beanDefinitionMap, essentially a ConcurrentHashMap; and BeanDefinition interface contains the Class information of this class and whether it is a single instance and so on;

When you need to create a bean object, you create the bean by traversing the beanDefinitionMap.

Main idea

BeanFactory implementation of the getBean method in AbstractBeanFactory, this method overload are called doGetBean method for implementation:

public Object getBean(String name) throws BeansException {
  return doGetBean(name, null, null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
  return doGetBean(name, requiredType, null, false);
}
public Object getBean(String name, Object... args) throws BeansException {
  return doGetBean(name, null, args, false);
}
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
    throws BeansException {
  return doGetBean(name, requiredType, args, false);
}

doGetBean

Let's take a look at the doGetBean method (it's a long one, so we'll focus on its overall idea and design points):

// parameterstypeCheckOnly:beanDoes the instance contain a type check
protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

  // analyzebeangenuinename,in the event thatbeanis a factory class,nameThe prefix will add&,Needs to be removed.
  String beanName = transformedBeanName(name);
  Object beanInstance;

  // Eagerly check singleton cache for manually registered singletons.
  Object sharedInstance = getSingleton(beanName);
  if (sharedInstance != null && args == null) {
    // Parameterless singleton fetches from cache
    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  }

  else {
    // in the event thatbeanInstances are still being created,then the exception is thrown directly
    if (isPrototypeCurrentlyInCreation(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
    }

    // in the event that bean definition existent in the Fatherbeanin plant,mandateBeanFactory Acquisition
    BeanFactory parentBeanFactory = getParentBeanFactory();
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
      // Not found -> check parent.
      String nameToLookup = originalBeanName(name);
      if (parentBeanFactory instanceof AbstractBeanFactory) {
        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
            nameToLookup, requiredType, args, typeCheckOnly);
      }
      else if (args != null) {
        // Delegation to parent with explicit args.
        return (T) (nameToLookup, args);
      }
      else if (requiredType != null) {
        // No args -> delegate to standard getBean method.
        return (nameToLookup, requiredType);
      }
      else {
        return (T) (nameToLookup);
      }
    }

    if (!typeCheckOnly) {
      // connects the dots betweenbeaninstance into thealreadyCreatedassembly,Mark thisbeanReady to create
      markBeanAsCreated(beanName);
    }

    StartupStep beanCreation = ("")
        .tag("beanName", name);
    try {
      if (requiredType != null) {
        ("beanType", requiredType::toString);
      }
      RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
      checkMergedBeanDefinition(mbd, beanName, args);

      // Make sure its dependencies are also initialized.
      String[] dependsOn = ();
      if (dependsOn != null) {
        for (String dep : dependsOn) {
          if (isDependent(beanName, dep)) {
            throw new BeanCreationException((), beanName,
                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
          }
          registerDependentBean(dep, beanName);
          try {
            getBean(dep); // Initialize theBean
          }
          catch (NoSuchBeanDefinitionException ex) {
            throw new BeanCreationException((), beanName,
                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
          }
        }
      }

      // establishBeanan actual example:singleton example
      if (()) {
        sharedInstance = getSingleton(beanName, () -> {
          try {
            // 真正establishbeanmethodologies
            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);
      }
      // establishBeanan actual example:original form
      else if (()) {
        // 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);
      }
      // establishBeanan actual example:groundbean(used form a nominal expression)scopeestablish
      else {
        String scopeName = ();
        if (!(scopeName)) {
          throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
        }
        Scope scope = (scopeName);
        if (scope == null) {
          throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
        }
        try {
          Object scopedInstance = (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);
        }
      }
    }
    catch (BeansException ex) {
      ("exception", ().toString());
      ("message", (()));
      cleanupAfterBeanCreationFailure(beanName);
      throw ex;
    }
    finally {
      ();
    }
  }

  return adaptBeanInstance(name, beanInstance, requiredType);
}

The logical flow is as follows:

  • Parses the real name of the bean, if the bean is a factory class, the name will be prefixed with &, which needs to be removed.
  • The unparameterized singleton first tries to fetch the
  • If the bean instance is still being created, an exception is thrown.
  • If the bean definition exists in the parent bean factory, delegate the bean definition to the parent bean factory.
  • Marks that an instance of this beanName is being created
  • Make sure its dependencies are also initialized
  • Real Creation
    • singleton case
    • prototype
    • Create a bean based on its scope

The next step is the actual creation of the bean

createBean

The overall flowchart of this method is shown below:

#createBean(, , [])

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    if (()) {
        ("Creating instance of bean '" + beanName + "'");
    }

    RootBeanDefinition mbdToUse = mbd;
    //class loading
    Class<?> resolvedClass = (mbd, beanName, new Class[0]);
    if (resolvedClass != null && !() && () != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        (resolvedClass);
    }

    try {
        //endorsementXMLdefinedbeanhit the nail on the headlook-upMethods for pre-processing
        ();
    } catch (BeanDefinitionValidationException var9) {
        throw new BeanDefinitionStoreException((), beanName, "Validation of method overrides failed", var9);
    }

    Object beanInstance;
    try {
        //Before Instantiation,null
        beanInstance = (beanName, mbdToUse);
        if (beanInstance != null) {//这里就是Before Instantiation去执行了 “Before and after initialization” workflow,Then it is possible to return a file that is notnull(used form a nominal expression)Bean
            return beanInstance;//Just return thisBeanThe object.,不会再往正常走后续(used form a nominal expression)SpringIt's a normal process.
        }
    } catch (Throwable var10) {
        throw new BeanCreationException((), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
    }

    try {
        //这个就是走正常(used form a nominal expression)SpringestablishBean(used form a nominal expression)方法
        beanInstance = (beanName, mbdToUse, args);
        if (()) {
            ("Finished creating instance of bean '" + beanName + "'");
        }

        return beanInstance;
    } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
        throw var7;
    } catch (Throwable var8) {
        throw new BeanCreationException((), beanName, "Unexpected exception during bean creation", var8);
    }
}

Before Instantiation

The bean's post processors, BeanPostProcessors, will be processed.

#resolveBeforeInstantiation

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null; if (!
    if (! ()) {
        // Check if there is a post processor
        if (! () && ()) {
            Class<? > targetType = (beanName, mbd).
            if (targetType ! = null) {
                // Before instantiation
                bean = (targetType, beanName); if (targetType != null) {/before instantiation
                if (bean ! = null) { //Normal case bean is null, if not Null
                    // then go ahead and execute the method after initialization. But in this case it won't go through the normal spring bean creation process and will return the bean object directly
                    bean = (bean, beanName); }
                }
            }
        }

         = bean ! = null.
    }

    return bean; }
}
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    Iterator var3 = ().iterator();
    //Take it to all the post-processors to execute
    while(()) {
        BeanPostProcessor bp = (BeanPostProcessor)();
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
            Object result = (beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }

    return null;
}

doCreateBean

#doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (()) {
        // factoryBeanObjectCache:It's stored.beanNameThe corresponding returned object
        // factoryBeanInstanceCache:It's stored.beanNamecorrespondingFactoryBeaninstance object
        instanceWrapper = (BeanWrapper)(beanName);
    }
    
    //1.instantiated
    if (instanceWrapper == null) {
        //Here's where the object construction begins
        instanceWrapper = (beanName, mbd, args);
    }
    
    //original object
    Object bean = ();
    Class<?> beanType = ();
    if (beanType != ) {
         = beanType;
    }

    synchronized() {
        if (!) {
            try {
                //Run the modification and merge. "BeanDefinition
                //We'll check here.Autowiredinjection point(InjectedELement),and add these injection points to thembdparticular propertyexternal
                (mbd, beanType, beanName);
            } catch (Throwable var17) {
                throw new BeanCreationException((), beanName, "Post-processing of merged bean definition failed", var17);
            }

             = true;
        }
    }
    
    //If the current creation is a single instancebean,and allows circular dependencies,And it's still in the process of being created,Then it's an early exposure.
    boolean earlySingletonExposure = () && && (beanName);
    if (earlySingletonExposure) {
        if (()) {
            ("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
        }
        
        //at this timebeanAttribute injection is not yet complete,is a very simple object
        //Construct an object factory to add to thesingletonFactoriescenter
        //Fourth call to post-processor
        (beanName, () -> {
            return (beanName, mbd, bean);
        });
    }
    
    //The object has been exposed.
    Object exposedObject = bean;

    try {
        //2. Filling Properties
        (beanName, mbd, instanceWrapper);
        //3.initializationBeanboyfriend
        exposedObject = (beanName, exposedObject, mbd);
    } catch (Throwable var18) {
        if (var18 instanceof BeanCreationException && (((BeanCreationException)var18).getBeanName())) {
            throw (BeanCreationException)var18;
        }

        throw new BeanCreationException((), beanName, "Initialization of bean failed", var18);
    }

    if (earlySingletonExposure) {
        // When resolving circular dependencies,(coll.) fail (a student)AServiceparticular property注入完了之后,surname ConggetSingletoncenter得到AService AOP之后的代理boyfriend
        Object earlySingletonReference = (beanName, false);
       
        if (earlySingletonReference != null) {
             // 如果提前暴露的boyfriend和经过了完整的生命周期后的boyfriend相等,则把代理boyfriend赋值给exposedObject
            // Eventually it will be added to thesingletonObjectscenter去
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            // 如果提前暴露的boyfriend和经过了完整的生命周期后的boyfriend不相等
            // allowRawInjectionDespiteWrappingIndicates that in the case of a cyclic dependency,have no other choice
            else if (! && (beanName)) {
                String[] dependentBeans = (beanName);
                Set<String> actualDependentBeans = new LinkedHashSet();
                String[] var12 = dependentBeans;
                int var13 = ;

                for(int var14 = 0; var14 < var13; ++var14) {
                    String dependentBean = var12[var14];
                    if (!(dependentBean)) {
                        (dependentBean);
                    }
                }

                if (!()) {
                    // otherbeanNot usedAServicefinal version
                    throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + (actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    try {
        //4.Registered Destruction Process
        (beanName, bean, mbd);
        return exposedObject;
    } catch (BeanDefinitionValidationException var16) {
        throw new BeanCreationException((), beanName, "Invalid destruction signature", var16);
    }
}

construct an object

createBeanInstanceTo create a bean instance is to return a raw object

#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    //1. Get the class of the bean, and verify that the access rights of the class are public.
    Class<? > beanClass = (mbd, beanName, new Class[0]);
    if (beanClass ! = null && ! (()) && ! ()) {
        throw new BeanCreationException((), beanName, "Bean class isn't public, and non-public access is not allowed: " + ());
    } else {

        //2. Extension points that Spring provides to the developer
        //If the developer wants to implement the process of creating an object himself, then, then an implementation class of Supplier can be provided.
        //When a Supplier implementation class exists in a BeanDefinition, Spring uses the get method of this class to get the instance
        // instead of going through Spring's creation logic.
        Supplier<? > instanceSupplier = (); if (instanceSupplier !
        if (instanceSupplier ! = null) {
            return (instanceSupplier, beanName); } else if (() !
        } else if (() ! = null) {
            //3. Instantiate the bean via FactoryMethod.
            // The name FactoryMethod is still common in xml, where the bean is created via a factory method.
            return (beanName, mbd, args); } else {
        } else {
            boolean resolved = false; boolean autowireNecessity
            boolean autowireNecessary = false;
            // If the parameters of the constructor method are not specified manually when the bean is created. Then look at the BeanDefinition to see if it has already determined which constructor to use.
            //Note: If the parameter is not specified manually, then it must be inferred automatically, so once the BeanDefinition has identified the constructor to be used, then it should be made autowireNecessary.
            // Then you have to use the autowireConstructor() method to construct a bean object.
            if (args == null) {
                synchronized() {
                    if ( ! = null) {
                        resolved = true; autowireNecessary = ;
                        autowireNecessary = ;
                    }
                }
            }

            if (resolved) {
                // A resolved value of true means that the bean's constructor method has been determined.
                return autowireNecessary ?
                (beanName, mbd, (Constructor[])null, (Object[])null)
                // If the constructor method has been determined, but the constructor parameter has not been determined, then it means that there is no constructor parameter, and the constructor is implemented with no parameters
                : (beanName, mbd);
            } else {
                // Inferring the constructor method
                Constructor<? >[] ctors = (beanClass, beanName);
                //finds out the constructor via BeanPostProcessor
                //or the autowire property of the BeanDefinition is AUTOWIRE_ CONSTRUCTOR
                //or the value of the J constructor parameter is specified in the BeanDefinition
                //or args are specified in getBean()
                if (ctors == null && () ! = 3 && ! () && (args)) {
                    ctors = (); return ctors !
                    return ctors ! = null ? (beanName, mbd, ctors, (Object[])null) : (beanName, mbd);
                } else {
                    // Perform constructor inference and instantiation
                    return (beanName, mbd, ctors, args); } else {
                }
            }
        }
    }
}

Filling Properties

Spring uses a post processor that implements the InstantiationAwareBeanPostProcessor to process the instantiated bean.

  • AutowiredAnnotationBeanPostProcessor for @Autowired annotation
  • CommonAnnotationBeanPostProcessor for @Resource annotation
  • ByName and byType|

#populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (()) {
            throw new BeanCreationException((), beanName, "Cannot apply property values to null instance");
        }
    } else {
        // You can provide an InstantiationAwareBeanPostProcessor to control the injection of properties into the object.
        // You can write your own InstantiationAwareBeanPostProcessor, and then override postProcessAfterInstantiation.
        if (! () && ()) {
            Iterator var4 = ().iterator();

            while(()) {
                BeanPostProcessor bp = (BeanPostProcessor)();
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    if (! ((), beanName)) {
                        return;
                    }
                }
            }
        }

        // Whether the property values are set in the BeanDefinition
        PropertyValues pvs = () ? () : null;
        int resolvedAutowireMode = (); // byname is the name of the bean to be found based on the name of the property, 1 is the bean.
        // byname is the name of the bean, 1 is byname.
        // bytype is to find the bean by the type of the parameter of the set method corresponding to the attribute, 2 is bytype.
        // Once the bean is found, the set method is called to inject it.
        if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
            MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs); if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
            if (resolvedAutowireMode == 1) {
                (beanName, mbd, bw, newPvs);
            }

            if (resolvedAutowireMode == 2) {
                (beanName, mbd, bw, newPvs); }
            }

            // To summarize
            // It's actually Spring's way of automatically finding a bean based on the set method of a class, byName, which is the name of the attribute of the base set method.
            // byType, that is, according to the type of the parameter of the set method to find the bean.
            // Note that after executing the code here, the attributes and the found values are stored in pvs, and no reflective assignment is done.
            pvs = newPvs; }
        }

        //After the execution of Spring's auto-injection, the beginning of the solution Autowired, here called instantiation callbacks
        boolean hasInstAwareBpps = (); boolean needsDepCheck = (); boolean needsDepCheck = ()
        boolean needsDepCheck = () ! = 0; boolean needsDepCheck = () !

        // @Autowired annotated AutowiredAnnotationBeanPostProcessor.
        // @Resource annotated CommonAnnotationBeanPos tProcessor .
        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = ();
            }

            Iterator var9 = ().iterator();

            while(()) {
                BeanPostProcessor bp = (BeanPostProcessor)(); if (bp instanceof InstantiationAwareBeanPostProcessor) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    // Call the BeanPostProcessor to parse @Autowired, @Resource, @Value to get the property values.
                    PropertyValues pvsToUse = ((PropertyValues)pvs, (), beanName); if (pvsToUse); // call BeanPostProcessor to parse @Autowired.
                    if (pvsToUse == null) {
                        if (filteredPds == null) {
                            filteredPds = (bw, );
                        }

                        pvsToUse = ((PropertyValues)pvs, filteredPds, (), beanName);
                        if (pvsToUse == null) {
                            return;
                        }
                    }

                    pvs = pvsToUse; }
                }
            }
        }

        if (needsDepCheck) {
            if (filteredPds == null) {
                filteredPds = (bw, );
            }

            (beanName, mbd, filteredPds, (PropertyValues)pvs);
        }

        if (pvs ! = null) {
            //pvs is actually the value that the property already corresponds to.
            //The logic here is to get the name and value to populate it through reflection
            (beanName, mbd, bw, (PropertyValues)pvs);
        }

    }
}

Initializing Bean Objects

Initialize the instance after populating the attributes by initializeBean

  1. Implement Aware: Check if there are three Aware implemented, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware.
  2. Before initialization: BeanPostProcessor
  3. Initialization: afterPropertiesSet, init-method
  4. After initialization: BeanPostProcessor, AOP

If it is a single bean, it is added to the singleton pool. If you want to use a singleton in the future, get it from the singleton pool.

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (() != null) {
        (() -> {
            (beanName, bean);
            return null;
        }, ());
    } else {
        //1.fulfillmentAware
        (beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !()) {
        //2.pre-initialization:就是fulfillment所有的后置处理器
        wrappedBean = (bean, beanName);
    }

    try {
        //3.initialization
        (beanName, wrappedBean, mbd);
    } catch (Throwable var6) {
        throw new BeanCreationException(mbd != null ? () : null, beanName, "Invocation of init method failed", var6);
    }

    if (mbd == null || !()) {
        //4. initialization后 AOPThis is where it's done.
        wrappedBean = (wrappedBean, beanName);
    }

    return wrappedBean;
}
Execute Aware

It is to see if there is any implementation of these three Aware, if there is, then execute the relevant method

#invokeAwareMethods

private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware)bean).setBeanName(beanName);
        }

        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = ();
            if (bcl != null) {
                ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
            }
        }

        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware)bean).setBeanFactory(this);
        }
    }

}
pre-initialization

Take all the post processors to process the bean, and when one processor returns null, it will no longer call the later processors to process it.

#applyBeanPostProcessorsBeforeInitialization

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;

    Object current;
    for(Iterator var4 = ().iterator(); (); result = current) {
        BeanPostProcessor processor = (BeanPostProcessor)();
        current = (result, beanName);
        if (current == null) {
            return result;
        }
    }

    return result;
}

There are 2 ways to complete the pre-initialization operation:

  1. TestBeanPostProcessor implements BeanPostProcessor and overrides the postProcessBeforeInitialization method.
  2. Use @PostConstruct. handled by the CommonAnnotationBeanPostProcessor handler. @PostConstruct is used after the instantiation of the bean has finished
initialization

#invokeInitMethods

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
    boolean isInitializingBean = bean instanceof InitializingBean;
    //in the event thatBeanRealizedInitializingBean,then processed
    if (isInitializingBean && (mbd == null || !("afterPropertiesSet"))) {
        if (()) {
            ("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }

        if (() != null) {
            try {
                (() -> {
                    //fulfillmentafterPropertiesSet
                    ((InitializingBean)bean).afterPropertiesSet();
                    return null;
                }, ());
            } catch (PrivilegedActionException var6) {
                throw ();
            }
        } else {
            ((InitializingBean)bean).afterPropertiesSet();
        }
    }

    if (mbd != null && () != ) {
        String initMethodName = ();
        if ((initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !(initMethodName)) {
            //fulfillment自定义的init-method
            (beanName, bean, mbd);
        }
    }

}
  1. Classes that implement the InitializingBean interface execute their afterPropertiesSet() method.
  2. Get the initMethod method from the BeanDefinition.

It can be configured in an xml file:

<bean  class="" init-method="initMethod"/>

Or @Bean annotation configuration:

@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
public UserService userService() {
    return new UserService();
}
post-initialization

getBeanPostProcessors() gets all post processors, including self-defined

#applyBeanPostProcessorsBeforeInitialization

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;

    Object current;
    for(Iterator var4 = ().iterator(); (); result = current) {
        BeanPostProcessor processor = (BeanPostProcessor)();
        current = (result, beanName);
        if (current == null) {
            return result;
        }
    }

    return result;
}

Special Note: . In the instantiation of the bean before the acquisition of the bean then will not perform spring normal process of creating beans, but directly call the initialization of the method to complete the initialization of the operation after the initialization.

Registered for destruction

Spring will remove all the beans in the container when the container is closed. if you need some beans to execute some logic before they are removed by Spring, Spring can do the same, then you need to register the bean as a DisposableBean when it finishes being created.

  1. Whether the bean is eligible to be registered as a DisposableBean and whether it has a destroyMethod.
  2. Whether or not there is a post processor that executes the destruction method.
  3. DisposableBeanAdapter
    1. Inferring the DestoryMethod
    2. Specified destroyMethod, AutoCloseable(close method), no shutdown method.
  4. Finish registering: that is, finish wrapping the DisposableBeanAdapter, put into the destruction container.
Eligibility to be registered as a DisposableBean
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = () != null ? () : null;
    //1. BeanIs there a registration forDisposableBeaneligibility criteria
    、、 It can't be a prototype.Bean(Because the prototypeBeanIt's not going in.Springcontainer),funnelrequiresDestructionmethod to see if it needs to be destroyed.。
    if (!() && (bean, mbd)) {
        if (()) {
            (beanName, new DisposableBeanAdapter(bean, beanName, mbd, (), acc));
        } else {
            Scope scope = (Scope)(());
            if (scope == null) {
                throw new IllegalStateException("No Scope registered for scope name '" + () + "'");
            }

            (beanName, new DisposableBeanAdapter(bean, beanName, mbd, (), acc));
        }
    }

}

Determining whether a bean has a destroyMethod method

protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
    // 1. RealizedDisposableBeaninterface orAutoCloseablelatch on to
    // 2. BeanDefinition is defined in thedestroyMethodName
    // 3. Does the class have a@PreDestroyannotated method
    // 4. leave it (to sb)DestructionAwareBeanPostProcessorDetermine if destruction is required
    return () !=
    && ((bean, mbd)
    || ()
    && (bean, ()));
}
Availability of post-processors to execute destruction methods

DestructionAwareBeanPostProcessor to identify whether a bean needs to be destroyed , and to the post processor to handle the logic before the destruction .

    public static boolean hasApplicableProcessors(Object bean, List<BeanPostProcessor> postProcessors) {
        if (!(postProcessors)) {
            for (BeanPostProcessor processor : postProcessors) {
                if (processor instanceof DestructionAwareBeanPostProcessor) {
                    DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
                    if ((bean)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
DisposableBeanAdapter

When a bean qualifies as a DisposableBean, Spring does not put the bean directly into the container that needs to be destroyed, but wraps it in a DisposableBeanAdapter object and puts it into the destruction container.

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
        AccessControlContext acc = (() != null ? getAccessControlContext() : null);
        if (!() && requiresDestruction(bean, mbd)) {
            if (()) {
    
                registerDisposableBean(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
            else {
                
                Scope scope = (());
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + () + "'");
                }
                (beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
        }
    }

The singleton bean destruction container is a Map with beanName as key and DisposableBean as value.

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    /** Disposable bean instances: bean name to disposable instance. */ 
    private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

    public void registerDisposableBean(String beanName, DisposableBean bean) {
        synchronized () {
            (beanName, bean);
        }
    }
}    

Inferring the DestoryMethod

When wrapping a bean as a DisposableBeanAdapter, go ahead and infer the destoryMethod.

    //Pick and choose which destruction method to execute,Returns only the method name。
    @Nullable
    private String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {
        //1.givendestroyMethodjust use
        String destroyMethodName = ();

        //2.Not specifieddestroyMethodName,hasn't(inferred),而且hasn't实现AutoCloseable(closemethodologies),come (or go) backnull
        if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
                (destroyMethodName == null && bean instanceof AutoCloseable)) {

            // Only perform destroy method inference or Closeable detection
            // in case of the bean not explicitly implementing DisposableBean

            // 3.there are(inferred),Or realizedAutoCloseable(closemethodologies)
            if (!(bean instanceof DisposableBean)) {
                try {
                    //hasn't实现DisposableBean(destroymethodologies),并且there areclosemethodologies就come (or go) back。
                    return ().getMethod(CLOSE_METHOD_NAME).getName();
                }
                catch (NoSuchMethodException ex) {
                    try {
                        //hasn'tclosewill report an error,看there arehasn'tshutdownmethodologies,there are就come (or go) back
                        return ().getMethod(SHUTDOWN_METHOD_NAME).getName();
                    }
                    catch (NoSuchMethodException ex2) {
                        //hasn'tshutdownmethodologies报错,But the anomaly was swallowed.,leave sth. untouched,come (or go) backnull
                        // no candidate destroy method found
                    }
                }
            }
            return null;
        }
        return ((destroyMethodName) ? destroyMethodName : null);
    }
  1. Inferred method name:
    1. If DestroyMethod is specified, it returns the specified.
    2. There is an inference mark or implementation of the AutoCloseable interface, and then see whether the implementation of the DisposableBean interface; if the implementation of the direct return to null, if not implemented on the inference of whether there is a public method of close, there is on the return, there is not to infer whether there is a public method of shutdown, there is on the return.
  2. Inferred Methods:
    @Nullable
    private Method findDestroyMethod(String name) {
        return ( ?
                ((), name) :
                (().getMethods(), name));
    }

Inferring a method from its name, getting the method object method with the least number of arguments, and reporting an error if the argument to method is greater than 1, or if it is equal to 1 and the argument type is not boolean.

Complete Registration

It is the DisposableBeanAdapter that completes the wrapping, and puts it into the destruction container.

Add to singleton pool

#getSingleton(, )

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    (beanName, "Bean name must not be null");
    synchronized() {
        Object singletonObject = (beanName);
        //If no instance exists,Then create a single instancebean
        if (singletonObject == null) {
            //be facing (us)beanDestruction in progress
            if () {
                throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
            }

            if (()) {
                ("Creating shared instance of singleton bean '" + beanName + "'");
            }

            (beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = == null;
            if (recordSuppressedExceptions) {
                 = new LinkedHashSet();
            }

            try {
                singletonObject = ();
                newSingleton = true;
            } catch (IllegalStateException var16) {
                singletonObject = (beanName);
                if (singletonObject == null) {
                    throw var16;
                }
            } catch (BeanCreationException var17) {
                BeanCreationException ex = var17;
                if (recordSuppressedExceptions) {
                    Iterator var8 = ();

                    while(()) {
                        Exception suppressedException = (Exception)();
                        (suppressedException);
                    }
                }

                throw ex;
            } finally {
                if (recordSuppressedExceptions) {
                     = null;
                }
                //Place the just-being-createdbeanNamesurname CongSingletonCreationRemove
                (beanName);
            }

            if (newSingleton) {
                //Place the created singletonbeanAdd to singleton poolsingletonObjectscenter
                (beanName, singletonObject);
            }
        }

        return singletonObject;
    }
}

destroy (by melting or burning)

The only concern here is the destruction of the singleton bean, which will be destroyed when the Spring container is shut down. if you don't manually shut down the container, then none of the above destroyMethods can be executed.

Summarize the logic of destruction:

  1. Before destroying: if there is a method annotated @PreDestory, execute it.
  2. If you have a customized destruction post-processor, destroy the beans one by one by calling the destoryBean via the postProcessBeforeDestruction method.
  3. On destruction: execute destory method if destroyMethod is implemented
  4. Perform customer-defined destruction: call invokeCustomDestoryMethod to execute the customized destroyMethod method on the bean

Manually execute the close method

#close

public void close() {
    synchronized() {
        ();
        if ( != null) {
            try {
                ().removeShutdownHook();
            } catch (IllegalStateException var4) {
            }
        }

    }
}

protected void doClose() {
    if (() && (false, true)) {
        if (()) {
            ("Closing " + this);
        }

        (this);

        try {
            ((ApplicationEvent)(new ContextClosedEvent(this)));
        } catch (Throwable var3) {
            ("Exception thrown from ApplicationListener handling ContextClosedEvent", var3);
        }

        if ( != null) {
            try {
                ();
            } catch (Throwable var2) {
                ("Exception thrown from LifecycleProcessor on context close", var2);
            }
        }

        ();
        ();
        ();
        if ( != null) {
            ();
            ();
        }

        (false);
    }

}

protected void destroyBeans() {
    ().destroySingletons();
}

#destroySingletons

public void destroySingletons() {
    if (()) {
        ("Destroying singletons in " + this);
    }

    synchronized() {
         = true;
    }

    String[] disposableBeanNames;
    synchronized() {//Containers registered for destruction
        disposableBeanNames = (());
    }
    
    //Traversal of registered destruction containers
    for(int i = - 1; i >= 0; --i) {
        (disposableBeanNames[i]);
    }

    ();
    ();
    ();
    ();
}

public void destroySingleton(String beanName) {
    (beanName);
    DisposableBean disposableBean;
    synchronized() {
        disposableBean = (DisposableBean)(beanName);
    }

    (beanName, disposableBean);
}


protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
    Set dependencies;
    //Handle dependencies firstbean
    synchronized() {
        dependencies = (Set)(beanName);
    }

    if (dependencies != null) {
        if (()) {
            ("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
        }

        Iterator var4 = ();

        while(()) {
            String dependentBeanName = (String)();
            (dependentBeanName);
        }
    }

    if (bean != null) {
        try {
            //beandestruction of,This is where the@PreDestroyannotated method respond in singing 自定义destruction of后置处理器
            ();
        } catch (Throwable var13) {
            if (()) {
                ("Destruction of bean with name '" + beanName + "' threw an exception", var13);
            }
        }
    }

    Set containedBeans;
    synchronized() {
        containedBeans = (Set)(beanName);
    }

    if (containedBeans != null) {
        Iterator var15 = ();

        while(()) {
            String containedBeanName = (String)();
            (containedBeanName);
        }
    }

    synchronized() {
        Iterator it = ().iterator();

        while(()) {
            Entry<String, Set<String>> entry = (Entry)();
            Set<String> dependenciesToClean = (Set)();
            (beanName);
            if (()) {
                ();
            }
        }
    }

    (beanName);
}

Interview questions column

Java interview questions columnIt's online, so feel free to visit.

  • If you don't know how to write a resume, resume projects don't know how to package them;
  • If there's something on your resume that you're not sure if you should put on it or not;
  • If there are some comprehensive questions you don't know how to answer;

Then feel free to private message me and I will help you in any way I can.