SoFunction
Updated on 2025-03-08

Spring source code analysis Bean instantiation

Preface

Let’s talk about the instantiation process of beans. In this article, the situation of bean circular dependence is not analyzed for the time being, because it is more complicated and will be placed in a separate article later for analysis.

Preparation

Look at the following sentenceAnnotationConfigApplicationContextClassicrefreshThe method starts with the following statement:

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

As can be seen from the official comments, this is used to complete the instantiation process of all non-lazy loading beans.

Let's write a simple bean for testing,DaoIt is also a bean that is left to spring to manage. spring will scan to this class and add it tobeanDefinitionMapandBeanDefinitionNamesmiddle:

@Component
public class MyService {
  @Autowired
  private Dao dao;

  public void query(){
    ("executing query method");
    ();
  }
}

Take a lookfinishBeanFactoryInitializationCode in:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  //If there is a conversionService in bdMap, initialization will be performed  //This bean can be used to provide data conversion function  if ((CONVERSION_SERVICE_BEAN_NAME) &&
      (CONVERSION_SERVICE_BEAN_NAME, )) {
    (
        (CONVERSION_SERVICE_BEAN_NAME, ));
  }
  if (!()) {
    (strVal -> getEnvironment().resolvePlaceholders(strVal));
  }
  //Initialize bean with type LoadTimeWeaverAware  // Can be used in AspectJ static weaving process  String[] weaverAwareNames = (, false, false);
  for (String weaverAwareName : weaverAwareNames) {
    getBean(weaverAwareName);
  }
  //Destroy the temporary ClassLoader generated in prepareBeanFactory() before  (null);
  //Frozen the modification to BeanDefinition here  //Prevent spring from modifying BeanDefinition during initialization  ();
  ();
}

In this method, the first step is to do some preparation work until the endbeanFactoryofpreInstantiateSingletonsThe method begins to prepare to perform the instantiation process of non-lazy loading beans. See firstpreInstantiateSingletonsThe first half of the method:

public void preInstantiateSingletons() throws BeansException {
  if (()) {
    ("Pre-instantiating singletons in " + this);
  }
  //Get the names of all beans  List<String> beanNames = new ArrayList<>();
  for (String beanName : beanNames) {
    //The operation of merging the BeanDefinition of the parent class has been performed    //When you can configure beans with XML, there is a parent attribute that can inherit class names, scopes, etc.    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    if (!() && () && !()) {
      //Judge it is FactoryBean      if (isFactoryBean(beanName)) {
        //If it is FactoryBean, add &        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
        if (bean instanceof FactoryBean) {
          final FactoryBean<?> factory = (FactoryBean<?>) bean;
          boolean isEagerInit;
          if (() != null && factory instanceof SmartFactoryBean) {
            isEagerInit = ((PrivilegedAction<Boolean>)
                    ((SmartFactoryBean<?>) factory)::isEagerInit,
                getAccessControlContext());
          }
          else {
            isEagerInit = (factory instanceof SmartFactoryBean &&
                ((SmartFactoryBean<?>) factory).isEagerInit());
          }
          if (isEagerInit) {
            getBean(beanName);
          }
        }
      }
      else { //The situation is not factoryBean        getBean(beanName);
      }
    }
  }
  ...

First frombeanDefinitionNamesGet all the listbeanName, perform traversal. Said beforeDefaultListableBeanFactoryA cached internallybeanDefinitionMap Map, and thisbeanDefinitionNamesFrom this, it can also be seen that the workload in encoding can be reduced to a certain extent through appropriate redundancy.

Before initializing the bean, there are 3 conditions: cannot be loaded for abstract classes, singleton beans, and non-lazy. Very easy to understand, I won't say more, I will explain it carefullyisFactoryBeanMethod to determine whether the bean isFactorybeanFactorybeanIt is a relatively special bean and is managed by spring container. Let's take a look at the interface definition:

public interface FactoryBean<T> {
  T getObject() throws Exception;
  Class<?> getObjectType();
  default boolean isSingleton() {
    return true;
  }
}

If a class is implementedFactoryBeanInterface, there will be two objects in that spring container, one isgetObjectThe object returned by the method, the other one is the current oneFactoryBeanThe object itself, and&Add onbeanNameMake a distinction before. For example:

@Component
public class MyFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new TestDao();
    }
    @Override
    public Class<?> getObjectType() {
        return ;
    }
}

test:

(("myFactoryBean"));
(("&myFactoryBean"));

result:

@fbd1f6
@1ce24091

forFactoryBeanTo obtain it,beanNamePrefix&, and then you will first determine whether it isSmartFactoryBeanandisEagerInitTrue, if so, callgetBeanThe method is initialized. Skip the content here and look directly at the important onesgetBeanmethod:

public Object getBean(String name) throws BeansException {
  return doGetBean(name, null, null, false);
}

Here is an empty method, continue to calldoGetBeanMethod, starting from this, is the core process of instantiating beans.

Instantiated bean

For the convenience of analysis, we number the classes and methods according to the call Shunxun to facilitate the analysis of the subsequent analysis process.

1. DoGetBean method of AbstractBeanFactory

As before, non-focused content is explained directly in the code with comments.

protected &lt;T&gt; T doGetBean(final String name, @Nullable final Class&lt;T&gt; requiredType,
    @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  final String beanName = transformedBeanName(name);
  Object bean;
  //Try to get it from the spring container first, if it is empty, instantiate it  Object sharedInstance = getSingleton(beanName);
  //Args is empty when calling getBean  //If it is not empty, it means that the caller does not want to get the bean, but creates the bean  if (sharedInstance != null &amp;&amp; args == null) {
    if (()) {
      if (isSingletonCurrentlyInCreation(beanName)) {
        ("Returning eagerly cached instance of singleton bean '" + beanName +
            "' that is not fully initialized yet - a consequence of a circular reference");
      }
      else {
        ("Returning cached instance of singleton bean '" + beanName + "'");
      }
    }
    /*
     * If it is an ordinary singleton bean, the following method will directly return sharedInstance
     * But if it is of FactoryBean type, you need to get the bean instance
     * If you want to obtain FactoryBean itself, you won't do any special treatment.
     * */
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  }
  else {
    //If the current thread has created this bean of prototype type, an exception will be thrown    if (isPrototypeCurrentlyInCreation(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
    }
    // If spring is not modified, the default parentBeanFactory is empty    BeanFactory parentBeanFactory = getParentBeanFactory();
    if (parentBeanFactory != null &amp;&amp; !containsBeanDefinition(beanName)) {
      String nameToLookup = originalBeanName(name);
      if (parentBeanFactory instanceof AbstractBeanFactory) {
        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
            nameToLookup, requiredType, args, typeCheckOnly);
      }
      else if (args != null) {
        return (T) (nameToLookup, args);
      }
      else {
        return (nameToLookup, requiredType);
      }
    }
    if (!typeCheckOnly) {
      //typeCheckOnly is false, added to the alreadyCreated Set collection, indicating that it has been created      //Prevent duplicate creation      markBeanAsCreated(beanName);
    }
    //The key part, create a singleton bean, or create a new prototype bean    try {
      final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
      checkMergedBeanDefinition(mbd, beanName, args);

      // Determine whether the current bean has dependencies. Here it refers to the situation where depends-on is used. You need to instantiate the dependency bean first.      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 + "'");
          }
          //Register dependency          registerDependentBean(dep, beanName);
          try {
            //Initialization is dependent bean            getBean(dep);
          }
          catch (NoSuchBeanDefinitionException ex) {
            throw new BeanCreationException((), beanName,
                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
          }
        }
      } 
      //This is where the bean instance is really created      if (()) {
        sharedInstance = getSingleton(beanName, () -&gt; {
          try {
            //Sentences that really create functions            return createBean(beanName, mbd, args);
          }
          catch (BeansException ex) {            
            destroySingleton(beanName);
            throw ex;
          }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
      }
      // Create an instance of prototype      else if (()) {        
        Object prototypeInstance = null;
        try {
          beforePrototypeCreation(beanName);
          prototypeInstance = createBean(beanName, mbd, args);
        }
        finally {
          afterPrototypeCreation(beanName);
        }
        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
      }
      //If it is not singleto and prototype, delegate to the corresponding implementation class to handle it.      else {
        String scopeName = ();
        final Scope scope = (scopeName);
        if (scope == null) {
          throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
        }
        try {
          Object scopedInstance = (beanName, () -&gt; {
            beforePrototypeCreation(beanName);
            try {
              return createBean(beanName, mbd, args);
            }
            finally {
              afterPrototypeCreation(beanName);
            }
          });
          bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
        }
      //Exception is thrown, code is omitted...  }
  //Type check, if normal, return, if exception is thrown  if (requiredType != null &amp;&amp; !(bean)) {
    try {
      T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
      if (convertedBean == null) {
        throw new BeanNotOfRequiredTypeException(name, requiredType, ());
      }
      return convertedBean;
    }
    catch (TypeMismatchException ex) {
      if (()) {
        ("Failed to convert bean '" + name + "' to required type '" +
            (requiredType) + "'", ex);
      }
      throw new BeanNotOfRequiredTypeException(name, requiredType, ());
    }
  }
  return (T) bean;
}

Before creating the bean, the first call isDefaultSingletonBeanRegistryofgetSingletonMethod, that is, spring tries to obtain it once before initializing a bean, and determines whether the object has been instantiated. If it already exists, it will be used directly. EntergetSingletonMethod, core code:

Object singletonObject = (beanName);

Take a looksingletonObjectsDefinition:

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

Here I will spoil it in advance. This map is used to store instantiated singleton beans, and in a narrow sense, it can be said thatsingletonObjectsIt's the spring container, and it uses itConcurrentHashMapto ensure the security of concurrent operations.

Because our bean is still in the creation stage, we will definitely not be able to obtain the instance from the map this time. Then run it down and take a look at the calledcreateBeanmethod.

2. The createBean method of AbstractAutowireCapableBeanFactory

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
  if (()) {
    ("Creating instance of bean '" + beanName + "'");
  }
  RootBeanDefinition mbdToUse = mbd;
  //Make sure the Class in BeanDefinition is loaded  Class&lt;?&gt; resolvedClass = resolveBeanClass(mbd, beanName);
  if (resolvedClass != null &amp;&amp; !() &amp;&amp; () != null) {
    mbdToUse = new RootBeanDefinition(mbd);
    (resolvedClass);
  }
  // Handle lookup-method and replace-method configurations  // In spring, lookup-method and replace-method are collectively called method overrides  try {
    ();
  }
  catch (BeanDefinitionValidationException ex) {
    throw new BeanDefinitionStoreException((),
        beanName, "Validation of method overrides failed", ex);
  }
  try {
    //Application of post-processor, if the bean returned by post-processor is not empty, it will be returned directly    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
      return bean;
    }
  }
  catch (Throwable ex) {
    throw new BeanCreationException((), beanName,
        "BeanPostProcessor before instantiation of bean failed", ex);
  }
  try {//Calling doCreateBean to create bean    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (()) {
      ("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
  }
  //Not important code omitted...}

I did a long preparation work before, but I still didn’t create a bean. The work of creating a bean was handed over todoCreateBeanThe method is completed.

3. DoCreateBean method of AbstractAutowireCapableBeanFactory

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    throws BeanCreationException {
  //BeanWrapper is a wrapper interface, and the real instantiation is BeanWrapperImpl  BeanWrapper instanceWrapper = null;
  if (()) {
    instanceWrapper = (beanName);
  }
  if (instanceWrapper == null) {
    //Create a bean instance and wrap the instance in the BeanWrapper implementation class object to return    instanceWrapper = createBeanInstance(beanName, mbd, args);
  }
  // Use BeanWrapper to generate a native object  final Object bean = ();
  Class&lt;?&gt; beanType = ();
  if (beanType != ) {
     = beanType;
  }
  // Allow post-processors to modify the merged bean definition.
  synchronized () {
    if (!) {
      try {
        //Execute the postprocessor MergedBeanDefinitionPostProcessor        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      }
      catch (Throwable ex) {
        throw new BeanCreationException((), beanName,
            "Post-processing of merged bean definition failed", ex);
      }
       = true;
    }
  }
  // Used to deal with circular dependencies, and will be analyzed separately later  boolean earlySingletonExposure = (() &amp;&amp;  &amp;&amp;
      isSingletonCurrentlyInCreation(beanName));
  if (earlySingletonExposure) {
    if (()) {
      ("Eagerly caching bean '" + beanName +
          "' to allow for resolving potential circular references");
    }
    //Execute the postprocessor    addSingletonFactory(beanName, () -&gt; getEarlyBeanReference(beanName, mbd, bean));
  }
  //So far, it's still the native object  Object exposedObject = bean;
  try {
    //Assign attributes and dependencies are very important    populateBean(beanName, mbd, instanceWrapper);
    //Execute the postprocessor and become a proxy object. AOP is the process completed here.    exposedObject = initializeBean(beanName, exposedObject, mbd);
  }
  //The intermediate non-important code is omitted...  return exposedObject;
}

Three more important tasks are done here:

  • ①, callcreateBeanInstanceMethod to create bean instance
  • ②, callpopulateBeanFill the attributes, and dependency injection is done here.
  • ③, callinitializeBean, execute various post-processors, execute various callback functions

In order, we will continue to talk about the process of creating bean forces in ①. After this process is finished, we will go back to analyze the attribute filling and callback methods.

4. The createBeanInstance method of AbstractAutowireCapableBeanFactory

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
  //Make sure the class is loaded  Class&lt;?&gt; beanClass = resolveBeanClass(mbd, beanName);

  //Detection of access permissions for a class spring is allowed to access public classes by default.  if (beanClass != null &amp;&amp; !(()) &amp;&amp; !()) {
    throw new BeanCreationException((), beanName,
        "Bean class isn't public, and non-public access not allowed: " + ());
  }

  Supplier&lt;?&gt; instanceSupplier = ();
  if (instanceSupplier != null) {
    return obtainFromSupplier(instanceSupplier, beanName);
  }

  /*
   *If the factory method is not empty, build the bean object through the factory method
   * factoryMethod is based on xml and is rarely used in actual work
   * */
  if (() != null) {
    return instantiateUsingFactoryMethod(beanName, mbd, args);
  }

  /*
   * From the original comments of spring, you can know that this is a ShortCut. When the same bean is built multiple times, you can use this ShortCut
   * The resolved and the bean will be set during the first instantiation process.
   * */
  boolean resolved = false;
  boolean autowireNecessary = false;
  if (args == null) {
    synchronized () {
      if ( != null) {
        resolved = true;
        //If the parameters of the constructor have been parsed, an example must be performed by a constructor with parameter        autowireNecessary = ;
      }
    }
  }
  if (resolved) {
    if (autowireNecessary) {
      //Construct bean object through automatic assembly of construction method      return autowireConstructor(beanName, mbd, null, null);
    }
    else {
      //By the default parameter-free construction method      return instantiateBean(beanName, mbd);
    }
  }

  //Spring currently doesn't know how to instantiate this bean, so I first get all the construction methods  //The postprocessor decides which constructors to return  Constructor&lt;?&gt;[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  /*
   * AUTOWIRE : 0-NO ,1-BY_NAME,2-BY_TYPE,3-CONSTRUCTOR
   * What you get here () is 0, which is NO
   * */
  if (ctors != null || () == AUTOWIRE_CONSTRUCTOR ||
      () || !(args)) {
    return autowireConstructor(beanName, mbd, ctors, args);
  }
  //Initialize using the default parameterless constructor  return instantiateBean(beanName, mbd);
}

If the bean has multiple construction methods, it will determine which one is used based on the parameters. The specific content is more complicated and will be prepared to be analyzed in a separate article later. If there is only a parameterless construction method or a construction method is not written, the parameterless construction method will be used by default for instantiation. This situation is only analyzed for the time being.

5. The instantiateBean method of AbstractAutowireCapableBeanFactory

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
  try {
    Object beanInstance;
    final BeanFactory parent = this;
    if (() != null) {
      beanInstance = ((PrivilegedAction&lt;Object&gt;) () -&gt;
          getInstantiationStrategy().instantiate(mbd, beanName, parent),
          getAccessControlContext());
    }
    else {
      // getInstantiationStrategy gets the instantiation strategy of the class      beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    }
    BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    initBeanWrapper(bw);
    return bw;
  }
  catch (Throwable ex) {
    throw new BeanCreationException(
        (), beanName, "Instantiation of bean failed", ex);
  }
}

Passed heregetInstantiationStrategyGet the instantiation policy of the class, which by default is to get a reflected instantiation policy. Then callinstantiateThe method is instantiated.

6. SimpleInstantiationStrategy's instantiate method

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
  // Check whether lookup-method or replace-method is configured in the bean configuration  //If configured, you need to use CGLIB to build bean object  if (!()) {
    Constructor&lt;?&gt; constructorToUse;
    synchronized () {
      constructorToUse = (Constructor&lt;?&gt;) ;
      if (constructorToUse == null) {
        final Class&lt;?&gt; clazz = ();
        if (()) {
          throw new BeanInstantiationException(clazz, "Specified class is an interface");
        }
        try {
          if (() != null) {
            constructorToUse = (
                (PrivilegedExceptionAction&lt;Constructor&lt;?&gt;&gt;) clazz::getDeclaredConstructor);
          }
          else {
            //Get the default constructor, even if it is not written, there will be one            constructorToUse = ();
          }
           = constructorToUse;
        }
        catch (Throwable ex) {
          throw new BeanInstantiationException(clazz, "No default constructor found", ex);
        }
      }
    }               
    //Instantiate using constructor method    return (constructorToUse);
  }
  else {
    //Instantiation using CGLIB    return instantiateWithMethodInjection(bd, beanName, owner);
  }
}

instantiateClassIn the method,Create an object through reflection:

//Set the constructor to be accessible(ctor);
//Reflection creates an objectreturn ((()) ?
   (ctor, args) : (args));

After running this, the instantiation process is completed, but the attribute has not been injected yet. Go back to the example we gave at the beginning, there is another Dao that has not been injected. In the next article, we will analyze the injection of the attributes next.

This is the article about Spring source code analysis Bean instantiation. For more relevant Spring Bean instantiation content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!