In the previous article, we introduced the source content of the doGetBean method. We know that the bean creation process has three scopes: singleton, multiinstance, and Scope, which all use createBean. This article will focus on createBean.


CreateBean method

/** * Create a bean instance for the given merged bean definition (and arguments). * The bean definition will already have been merged with the parent definition * in case of a child definition. * <p>All bean retrieval methods delegate to  this method for actual bean creation. *@param beanName the name of the bean
 * @param mbd the merged bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return a new instance of the bean
 * @throws BeanCreationException if the bean could not be created
 */
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException;
Copy the code

In AbstractBeanFactory class, have createBean interface, specific creation process to the subclasses implement: AbstractAutowireCapableBeanFactory

/** * Central method of this class: Creates a bean instance, creates a bean instance, * populates the bean instance, applies post-processors, etc@see #doCreateBean
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Resolve the bean class name to a class referenceClass<? > resolvedClass = resolveBeanClass(mbd, beanName);// If the resolvedClass is not empty and there is no beanClass in the bean definition, and the bean definition has a beanClassName
   if(resolvedClass ! =null&&! mbd.hasBeanClass() && mbd.getBeanClassName() ! =null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   // Prepare method overwrite
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      // Give BeanPostProcessors a chance to create proxy objects
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if(bean ! =null) {
         returnbean; }}catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      // Create a native bean instance
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); }}Copy the code

MbdToUse. PrepareMethodOverrides () method, is to verify whether current method is overloaded, if this method overloading the only once, and then set the overloaded to false, to avoid parameter type checks. Because if this method is overloaded multiple times, the bean instance is instantiated and matched by parameter type, which takes a lot of time.

In Spring, you can override two methods: look-method and replace-method.

public class User {
   public void showUser(a) {
       System.out.println("User..."); }}Copy the code
public class Student extends User {

    @Override
    public void showUser(a) {
        System.out.println("Student..."); }}Copy the code
public abstract class DemoTest {

    public void showUser(a) {
        getBean().showUser();
    }

    public abstract User getBean(a);

    public abstract User getBean(String name);
}
Copy the code
<bean id="demoTest" class="edu.demo.spring.instantiate.DemoTest" >
   <lookup-method name="getBean" bean="user"></lookup-method>
</bean>
<bean id="student" class="edu.demo.spring.instantiate.Student" />
<bean id="user" class="edu.dongnao.courseware.spring.instantiate.User" />
Copy the code

ResolveBeforeInstantiation method is by calling InstantiationAwareBeanPostProcessor inside, the method of before and after the bean instantiation of some processing, here is an extension point, it will be returned to the bean instance proxy objects, To interfere with bean instantiation.

// Package visible field indicating that the handler has been started before and after bean instantiation
@Nullable
volatile Boolean beforeInstantiationResolved;
Copy the code
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   If the handler before and after the bean instantiation has already started, execute the following code
   if(! Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.
      // Make sure that the bean class has actually been parsed
      / / if the bean is not defined by the Spring container himself, and holds a InstantiationAwareBeanPostProcessors
      if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {// Determine the target type for the given bean definitionClass<? > targetType = determineTargetType(beanName, mbd);if(targetType ! =null) {
            // Bean processing before instantiation
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if(bean ! =null) {
               // Bean processing after instantiationbean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean ! =null);
   }
   return bean;
}
Copy the code

DoCreateBean method

/** Cache of unfinished FactoryBean instances: FactoryBean name to BeanWrapper. */
private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>();
Copy the code
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean definition
   BeanWrapper instanceWrapper = null;
   // If the bean is a singleton, it is fetched from the cache and then removed
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   // This step is the main step in creating the bean instance, which uses some simple strategies to instantiate the bean
   // Factory method, constructor, simple initialization
   if (instanceWrapper == null) {
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   // Get the wrapped instance object
   Object bean = instanceWrapper.getWrappedInstance();
   // Get the type of the wrapped instance objectClass<? > beanType = instanceWrapper.getWrappedClass();// If the type is not an empty bean, the assignment is made
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }
}
Copy the code

At bean instantiation time, the bean is wrapped in a BeanWrapper. BeanWrapper has the following functions:

  • The packing of the Bean
  • Property editor
  • Property editor registry
  • Type converter

CreateBeanInstance method

/** Common lock for the four constructor fields below. */
final Object constructorArgumentLock = new Object();

/** Package-visible field for caching the resolved constructor or factory method. */
// Package visible fields are used to cache parsed constructors and factory methods
@Nullable
Executable resolvedConstructorOrFactoryMethod;

/** Package-visible field that marks the constructor arguments as resolved. */
// Package visible field, used to indicate that the constructor parameters have been resolved
boolean constructorArgumentsResolved = false;
Copy the code
/** * Use the instantiation strategy to create an instance of the specified bean * factory method, constructor autowiring, simple instantiation */
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   // Make sure bean class is actually resolved at this point.
   // Parse to get the bean's corresponding classClass<? > beanClass = resolveBeanClass(mbd, beanName);// If beanClass is not empty and the beanClass modifier is not public
   // If access to non-public constructors and methods is not allowed, throw an exception
   if(beanClass ! =null&&! Modifier.isPublic(beanClass.getModifiers()) && ! mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }

   // If there is a Supplier instantiation callback interface, an instance object is created using the given callback methodSupplier<? > instanceSupplier = mbd.getInstanceSupplier();if(instanceSupplier ! =null) {
      return obtainFromSupplier(instanceSupplier, beanName);
   }

   // If a factory method exists, that is, 'factory-method' is configured, then this method is called to create an instance object
   if(mbd.getFactoryMethodName() ! =null) {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

   // Shortcut when re-creating the same bean...
   // The constructor of the bean definition has been resolved
   // Because finding the matching constructor is a tedious process, we will set it to the bean definition after finding it
   // Avoid repeating the search for a matching constructor
   boolean resolved = false;
   boolean autowireNecessary = false;
   if (args == null) {
      / / lock
      synchronized (mbd.constructorArgumentLock) {
         // The constructor has been resolved
         if(mbd.resolvedConstructorOrFactoryMethod ! =null) {
            resolved = true;
            // If the method has parameters, set them hereautowireNecessary = mbd.constructorArgumentsResolved; }}}// If the constructor or factory method has been resolved
   if (resolved) {
      // If there are parameters, instantiate the bean using the following method
      if (autowireNecessary) {
         return autowireConstructor(beanName, mbd, null.null);
      }
      else {
         // Instantiate the bean without arguments using the following method
         returninstantiateBean(beanName, mbd); }}// Candidate constructors for autowiring?
   // If none of the above is instantiated, it means that the constructor or factory method has not been resolved
   
   / / get some by SmartInstantiationAwareBeanPostProcessor constructorConstructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);// If the constructor is not empty and is injected through the constructor, the constructor holds construction parameters or defines some parameters
   if(ctors ! =null|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);
   }

   // Preferred constructors for default construction?
   // Get the preferred constructor
   ctors = mbd.getPreferredConstructors();
   if(ctors ! =null) {
      return autowireConstructor(beanName, mbd, ctors, null);
   }

   // No special handling: simply use no-arg constructor.
   // If none of the above is instantiated, the default constructor is used, that is, the constructor with no arguments
   return instantiateBean(beanName, mbd);
}
Copy the code

To summarize the steps:

  1. First, obtain the beanClass corresponding to beanName
  2. It then decides that the beanClass is not empty, the modifier is not public, and access to non-public methods is not allowed, so it throws an exception
  3. If the Supplier instantiation callback interface exists, an instance object is created using the given callback method, which calls the method obtainFromSupplier
  4. If the configuration factory – method, then use the factory method to instantiate the bean, instantiateUsingFactoryMethod calls the method
  5. This is followed by a wave of judgments to determine whether the constructor defined by the bean has been resolved, whether it has parameters, and whether the parameters have been resolved
  6. The autowireConstructor method is called to instantiate the bean if the constructor has been parsed and has parameters, or the instantiateBean method is called to instantiate the bean if there are no parameters
  7. If the bean is not instantiated above, get some constructor defined by the bean, if the constructor is not empty and is injected through the constructor, and the constructor defines some parameters, or passes some parameters outside of the getBean, The autowireConstructor method is called to instantiate the bean
  8. If there is still no instantiation, get the preferred constructor, and if so, call the autowireConstructor method to instantiate the bean
  9. Finally, without instantiating the bean above, the default constructor, the no-argument constructor, is used to instantiate the bean and the instantiateBean method is called

ObtainFromSupplier method

/** * The name of the currently created bean, for implicit dependency registration * on getBean etc invocations triggered from a user-specified Supplier callback. */
private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");
Copy the code
/** * get a bean instance * from a given vendor@param instanceSupplier the configured supplier
 * @param beanName the corresponding bean name
 * @return a BeanWrapper for the new instance
 * @since 5.0
 * @see #getObjectForBeanInstance
 */
protected BeanWrapper obtainFromSupplier(Supplier
        instanceSupplier, String beanName) {
   Object instance;

   // Get the name of the bean created by the current thread
   String outerBean = this.currentlyCreatedBean.get();
   // Set the name of the bean created by the current thread
   this.currentlyCreatedBean.set(beanName);
   try {
      // Returns a bean instance by calling the Supplier's get method
      instance = instanceSupplier.get();
   }
   finally {
      if(outerBean ! =null) {
         // Set the name of the bean created by the current thread
         this.currentlyCreatedBean.set(outerBean);
      }
      else {
         / / remove
         this.currentlyCreatedBean.remove(); }}// If instance is empty, NullBean empty objects are created
   if (instance == null) {
      instance = new NullBean();
   }
   // Encapsulate the instantiated bean as a BeanWrapper
   BeanWrapper bw = new BeanWrapperImpl(instance);
   // Initialize the BeanWrapper object
   initBeanWrapper(bw);
   // Finally back out
   return bw;
}
Copy the code

Summary steps:

  1. Calling the Supplier’s get method returns a bean instance object
  2. The bean instance object is wrapped with a BeanWrapper
  3. Initialize the BeanWrapper object

The Supplier interface is also used to create objects. Instead of a bean factory, a simple example is as follows:

public class SupplierBean {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        GenericBeanDefinition definition = new GenericBeanDefinition();
        definition.setBeanClass(People.class);
        definition.setInstanceSupplier(SupplierBean::getPeople);
        context.registerBeanDefinition("user2", definition);
        context.refresh();
    }


    private static People getPeople(a) {
        return new People("Cui flower");
    }

    static class People {

        private String name;

        public People(String name) {
            this.name = name; }}}Copy the code

InstantiateUsingFactoryMethod method

protected BeanWrapper instantiateUsingFactoryMethod(
      String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

   return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
Copy the code

Create ConstructorResolver object, then calls the instantiateUsingFactoryMethod method:

public BeanWrapper instantiateUsingFactoryMethod(
      String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {}Copy the code

The above method is longer, and the following is divided in order.

// Create the BeanWrapperImpl object
BeanWrapperImpl bw = new BeanWrapperImpl();
// Initialize BeanWrapperImpl and set the ConversionService type converter
// The custom property editor is registered
this.beanFactory.initBeanWrapper(bw);

/ / factory bean
Object factoryBean;
// The class of the factory methodClass<? > factoryClass;// Is a static factory
boolean isStatic;

// Get the name of the factory bean
String factoryBeanName = mbd.getFactoryBeanName();
// If the name of the factory bean is not empty, that is, factory-bean is not configured.
// means this is a non-static factory
if(factoryBeanName ! =null) {
   // If the bean obtained in the bean definition matches the bean being created, an exception is thrown
   // The factory bean reference points to the same bean definition
   if (factoryBeanName.equals(beanName)) {
      throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
            "factory-bean reference points back to the same bean definition");
   }
   // Get the factory bean, the bean of the factory method's class, otherwise there is no way to call the factory method
   factoryBean = this.beanFactory.getBean(factoryBeanName);
   // If the bean definition is a singleton and the bean exists in the bean factory, throw an exception and repeat the creation
   if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
      throw new ImplicitlyAppearedSingletonException();
   }
   // Get the factory class
   factoryClass = factoryBean.getClass();
   // Mark it as a non-static factory
   isStatic = false;
}
else {
   // It's a static factory method on the bean class.
   // This is a static factory. If the corresponding beanClass is not found, the method cannot be called and an exception is thrown
   if(! mbd.hasBeanClass()) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
            "bean definition declares neither a bean class nor a factory-bean reference");
   }
   Static factories do not require factory beans, set to null here
   factoryBean = null;
   // Get the factory beanClass
   factoryClass = mbd.getBeanClass();
   // Mark it as a static factory
   isStatic = true;
}
Copy the code

The above part of the code is mainly used to get information about the factory method, continue to see:

// Package visible field, indicating that the constructor has been resolved
boolean constructorArgumentsResolved = false;

// Package visible fields, parameter fields that have been fully parsed in the cache
@Nullable
Object[] resolvedConstructorArguments;

// Package visible field, the parameter field in the cache to be parsed
@Nullable
Object[] preparedConstructorArguments;
Copy the code
// Factory method object
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
// Related parameters
Object[] argsToUse = null;

// If the parameter is specified by the getBean method, use it directly
if(explicitArgs ! =null) {
   argsToUse = explicitArgs;
}
// Otherwise, get the factory methods and parameters through the bean definition
else {
   Object[] argsToResolve = null;
   / / lock
   synchronized (mbd.constructorArgumentLock) {
      factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
      // If the factory method has been parsed and the parameters have been parsed
      if(factoryMethodToUse ! =null && mbd.constructorArgumentsResolved) {
         // Found a cached factory method...
         // Parsed parameters
         argsToUse = mbd.resolvedConstructorArguments;
         // If it is empty, try to get the unparsed argument
         if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; }}}// If an unparsed parameter is obtained, the following method is called to parse it
   if(argsToResolve ! =null) {
      // Process parameter values to perform some type conversions, such as converting the configured String type to an Int: A("1") to A(1)
      argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true); }}Copy the code

The above source content is to try to obtain the factory method and parameter from the cache, can not obtain the following code:

// If the factory method and its parameters are not available, go to the following code
if (factoryMethodToUse == null || argsToUse == null) {
   // Need to determine the factory method...
   // Try all methods with this name to see if they match the given arguments.
   // Get the instance class of the factory method, as it may be a cglib wrapped class
   factoryClass = ClassUtils.getUserClass(factoryClass);

   List<Method> candidates = null;
   //
   if (mbd.isFactoryMethodUnique) {
      // Get the factory method
      if (factoryMethodToUse == null) {
         factoryMethodToUse = mbd.getResolvedFactoryMethod();
      }
      // Get all candidate factory methods
      if(factoryMethodToUse ! =null) { candidates = Collections.singletonList(factoryMethodToUse); }}// If the candidate factory method is empty
   if (candidates == null) {
      candidates = new ArrayList<>();
      // Get all the methods in the class of the factory method
      Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
      // filter through
      for (Method candidate : rawCandidates) {
         IsStatic = isStatic
         // If the factory method name is the same as defined, it is added to the collection of candidate methods
         if(Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) { candidates.add(candidate);  }}}// If only one matching method is found and the explicitArgs argument passed in the getBean is empty,
   // If there are no arguments in the bean definition, call this method to instantiate it and return it
  if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
   Method uniqueCandidate = candidates.get(0);
   if (uniqueCandidate.getParameterCount() == 0) {
      mbd.factoryMethodToIntrospect = uniqueCandidate;
      synchronized (mbd.constructorArgumentLock) {
         mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
         mbd.constructorArgumentsResolved = true;
         mbd.resolvedConstructorArguments = EMPTY_ARGS;
      }
      bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
      returnbw; }}Copy the code

With the above code, we have found all the factory methods that match, so which method really matches, continue to read:

// If the factory method is greater than 1, sort first
if (candidates.size() > 1) {  // explicitly skip immutable singletonList
  // The constructor for the public modifier takes precedence, then descending according to the number of arguments
  // Non-public constructors are in descending order according to the number of arguments
   candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
}

// Store the parsed method parameter values
ConstructorArgumentValues resolvedValues = null;
// Whether the constructor is injected
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
// A collection of matching methods
Set<Method> ambiguousFactoryMethods = null;

// Determine the number of method arguments. The matched method parameters should be equal to or more than that

// The minimum number of parameters for the method
int minNrOfArgs;
// If a parameter is specified in getBean, use it as the minimum number of parameters
if(explicitArgs ! =null) {
   minNrOfArgs = explicitArgs.length;
}
// Otherwise, get the minimum value of the parameter from the bean definition
else {
   // We don't have arguments passed in programmatically, so we need to resolve the
   // arguments specified in the constructor arguments held in the bean definition.
   // If there are parameter values in the bean definition
   if (mbd.hasConstructorArgumentValues()) {
      // Get the method parameters
      ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
      resolvedValues = new ConstructorArgumentValues();
      // Parses the defined parameter values and returns the number of parameters
      minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
   }
   else {
     // No parameter, minimum value is 0
      minNrOfArgs = 0; }}/ / record UnsatisfiedDependencyException abnormal collection
LinkedList<UnsatisfiedDependencyException> causes = null;
Copy the code

The above code, first of all to find the factory method to sort, and then determine the method parameter input number, after finding a matching method, is based on the number of parameters and their type to match.

// Iterate over the candidate methods
for (Method candidate : candidates) {
   // Get the number of method parameters
   int parameterCount = candidate.getParameterCount();

   The number of method parameters must be greater than or equal to the minimum parameter value
   if (parameterCount >= minNrOfArgs) {
      // Save the parameter object
      ArgumentsHolder argsHolder;

      // Get the type of the method parameterClass<? >[] paramTypes = candidate.getParameterTypes();// If a parameter is specified by getBean, use it directly
      if(explicitArgs ! =null) {
         // Explicit arguments given -> arguments length must match exactly.
         // The length of the specified argument must match exactly
         if(paramTypes.length ! = explicitArgs.length) {continue;
         }
         // Create ArgumentsHolder objects
         argsHolder = new ArgumentsHolder(explicitArgs);
      }
      else {
         // Otherwise use the following code to parse the parameters
         // Resolved constructor arguments: type conversion and/or autowiring necessary.
         try {
            String[] paramNames = null;
            // Get the parameter name probe
            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
            if(pnd ! =null) {
               // Get the method parameter name
               paramNames = pnd.getParameterNames(candidate);
            }
            // Create an ArgumentsHolder object given the parsing argument
            argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
                  paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
         }
         catch (UnsatisfiedDependencyException ex) {
            if (logger.isTraceEnabled()) {
               logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "'." + ex);
            }
            // Swallow and try next overloaded factory method.
            if (causes == null) {
               causes = new LinkedList<>();
            }
            causes.add(ex);
            continue; }}// Get the best matching method according to the weight
      // Determine whether to parse in loose mode or strict mode
      // Loose mode: use the "closest mode" for matching
      // Strict pattern: When parsing a constructor, everything must match, otherwise an exception is thrown
      int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
      // Choose this factory method if it represents the closest match.
      // If the factory method is used as an approach, then the factory method is used
      if (typeDiffWeight < minTypeDiffWeight) {
         factoryMethodToUse = candidate;
         argsHolderToUse = argsHolder;
         argsToUse = argsHolder.arguments;
         minTypeDiffWeight = typeDiffWeight;
         ambiguousFactoryMethods = null;
      }
      // Find out about ambiguity: In case of the same type difference weight
      // for methods with the same number of parameters, collect such candidates
      // and eventually raise an ambiguity exception.
      // However, only perform that check in non-lenient constructor resolution mode,
      // and explicitly ignore overridden methods (with the same parameter signature).
      // If a method with the same number of arguments has the same type of differential weight, add it to ambiguousFactoryMethods
      // However, this check can only be performed in non-permissive constructor parsing mode
      // And explicitly ignores the overridden method (with the same parameter signature)
      else if(factoryMethodToUse ! =null&& typeDiffWeight == minTypeDiffWeight && ! mbd.isLenientConstructorResolution() && paramTypes.length == factoryMethodToUse.getParameterCount() && ! Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {if (ambiguousFactoryMethods == null) {
            ambiguousFactoryMethods = newLinkedHashSet<>(); ambiguousFactoryMethods.add(factoryMethodToUse); } ambiguousFactoryMethods.add(candidate); }}}Copy the code

The above is a long code that first iterates through all the candidate methods, then resolves the method’s input parameters, and finally retrieves the best match method.

if (factoryMethodToUse == null || argsToUse == null) {
   if(causes ! =null) {
      UnsatisfiedDependencyException ex = causes.removeLast();
      for (Exception cause : causes) {
         this.beanFactory.onSuppressedException(cause);
      }
      throw ex;
   }
   //... Omitted code
   
   // Cache the parsed factory methods and parameters to prevent them from being parsed again the next time they are used
   if (explicitArgs == null&& argsHolderToUse ! =null) { mbd.factoryMethodToIntrospect = factoryMethodToUse; argsHolderToUse.storeCache(mbd, factoryMethodToUse); }}Copy the code

Finally, execute the following code:

// Call the factory method to create the instance, set it to bw, and return
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
Copy the code

The last call in SimpleInstantiationStrategy instantiate method in the class:

Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
try {
   currentlyInvokedFactoryMethod.set(factoryMethod);
   // Call the factory method
   Object result = factoryMethod.invoke(factoryBean, args);
   if (result == null) {
      result = new NullBean();
   }
   return result;
}
finally {
   if(priorInvokedFactoryMethod ! =null) {
      currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
   }
   else{ currentlyInvokedFactoryMethod.remove(); }}Copy the code

As you can see, invoke is used to invoke the factory method. The whole process above is very long, so let’s summarize the steps.

Summary steps:

  1. The BeanWrapperImpl object is created, then initialized, the ConversionService type converter is set, and a custom property editor is registered
  2. Then factoryBeanName determines whether the factory method is a static factory
  3. Try to get the factory method and its corresponding parameters from the cache
  4. If you can’t find any of the factory methods that match, then match them based on the number of parameters in the method
  5. Finally, the bean is instantiated using the reflection call factory method

In short, get the factory method that best matches, then get the relevant parameters, and finally call that factory method to instantiate the bean.

AutowireConstructor method

AutowireConstructor method and instantiateUsingFactoryMethod essentially similar, one is looking for a factory method, one is looking for a constructor, code there are a lot of similarities, then look at the code:

protected BeanWrapper autowireConstructor(
      String beanName, RootBeanDefinition mbd, @NullableConstructor<? >[] ctors,@Nullable Object[] explicitArgs) {

   return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
Copy the code

Create the ConstructorResolver object and call the autowireConstructor method:

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
      @NullableConstructor<? >[] chosenCtors,@Nullable Object[] explicitArgs) {}
Copy the code

This code is also longer, so let’s break it up.

// Create the BeanWrapperImpl object
BeanWrapperImpl bw = new BeanWrapperImpl();
// Initialize BeanWrapperImpl and set the ConversionService type converter
// The custom property editor is registered
this.beanFactory.initBeanWrapper(bw);

// constructorConstructor<? > constructorToUse =null;
ArgumentsHolder argsHolderToUse = null;
// Constructor parameters
Object[] argsToUse = null;

// If a parameter is set in getBean, use it directly
if(explicitArgs ! =null) {
   argsToUse = explicitArgs;
}
// Otherwise, try to get the parsed constructors and parameters from the bean definition
else {
   // This is to prevent parsing again, as it may have already been parsed
   Object[] argsToResolve = null;
   / / lock
   synchronized (mbd.constructorArgumentLock) {
      // Get the parsed constructorconstructorToUse = (Constructor<? >) mbd.resolvedConstructorOrFactoryMethod;// If the parsed constructor is not empty and the parameters are parsed
      if(constructorToUse ! =null && mbd.constructorArgumentsResolved) {
         // Found a cached constructor...
         argsToUse = mbd.resolvedConstructorArguments;
         // If the parsed construct parameter obtained is empty, try to retrieve the unparsed construct parameter from the bean definition
         if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; }}}// If an unparsed construct parameter is obtained, the following method is called to parse it
   if(argsToResolve ! =null) {
      argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true); }}Copy the code

The above code first tries to get the constructor and argument, if not, go to the following code:

// If the corresponding constructor and parameter were not found in the previous step, start looking for a matching constructor
if (constructorToUse == null || argsToUse == null) {
   // Take specified constructors, if any.
   // Get all constructors. If a collection of constructors is specified, use the collection chosenCtorsConstructor<? >[] candidates = chosenCtors;if (candidates == null) {
      // Get the beanClassClass<? > beanClass = mbd.getBeanClass();try {
         candidates = (mbd.isNonPublicAccessAllowed() ?
               beanClass.getDeclaredConstructors() : beanClass.getConstructors());
      }
      catch (Throwable ex) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "Resolution of declared constructors on bean Class [" + beanClass.getName() +
               "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); }}// If only one constructor is found and the argument passed by getBean is empty
   // And the bean definition has no arguments, call the constructor directly to return an instance of the bean
   if (candidates.length == 1 && explicitArgs == null&&! mbd.hasConstructorArgumentValues()) { Constructor<? > uniqueCandidate = candidates[0];
      if (uniqueCandidate.getParameterCount() == 0) {
         synchronized (mbd.constructorArgumentLock) {
            mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
            mbd.constructorArgumentsResolved = true;
            mbd.resolvedConstructorArguments = EMPTY_ARGS;
         }
         bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
         returnbw; }}}Copy the code

The above part of the code starts to get constructors and methods.

// Need to resolve the constructor.
// Whether it is constructor injection
booleanautowiring = (chosenCtors ! =null ||
      mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// Store the parsed method parameter values
ConstructorArgumentValues resolvedValues = null;

// The minimum number of method parameter values
int minNrOfArgs;
// If the parameter passed by getBean is not empty, its length is used as the minimum number of parameter values
if(explicitArgs ! =null) {
   minNrOfArgs = explicitArgs.length;
}
// Otherwise, get from the bean definition
else {
   // Get the construction parameters
   ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
   resolvedValues = new ConstructorArgumentValues();
   // Parse the construct parameters and return the number of parameters
   minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
Public takes precedence over the number of arguments
AutowireUtils.sortConstructors(candidates);
intminTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<? >> ambiguousConstructors =null;
LinkedList<UnsatisfiedDependencyException> causes = null;
Copy the code

Get the number of input arguments to the constructor. Match the number of input arguments to the constructor.

// Iterate over all constructors
for(Constructor<? > candidate : candidates) {// Get the number of construction parameters
   int parameterCount = candidate.getParameterCount();

   // If matching constructors and arguments already exist, the loop is broken
   if(constructorToUse ! =null&& argsToUse ! =null && argsToUse.length > parameterCount) {
      // Already found greedy constructor that can be satisfied ->
      // do not look any further, there are only less greedy constructors left.
      break;
   }
   // If the constructor argument is less than the minimum argument value, it does not conform
   if (parameterCount < minNrOfArgs) {
      continue;
   }

  // The object used to hold the parameterArgumentsHolder argsHolder; Class<? >[] paramTypes = candidate.getParameterTypes();if(resolvedValues ! =null) {
      try {
         // Get the constructor parameter name
         String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
         if (paramNames == null) {
            // If not, use ParameterNameDiscoverer
            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
            if(pnd ! =null) { paramNames = pnd.getParameterNames(candidate); }}// Create an ArgumentsHolder object given the parsing argument
         argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
               getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
      }
      catch (UnsatisfiedDependencyException ex) {
         if (logger.isTraceEnabled()) {
            logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "'." + ex);
         }
         // Swallow and try next constructor.
         if (causes == null) {
            causes = new LinkedList<>();
         }
         causes.add(ex);
         continue; }}else {
      // Explicit arguments given -> arguments length must match exactly.
      // The given explicit argument -> the length of the argument must match exactly
      if(parameterCount ! = explicitArgs.length) {continue;
      }
      // Create ArgumentsHolder objects
      argsHolder = newArgumentsHolder object (explicitArgs); }// Get the best matching method according to the weight
  // Determine whether to parse in loose mode or strict mode
  // Loose mode: use the "closest mode" for matching
  // Strict pattern: When parsing a constructor, everything must match, otherwise an exception is thrown
   int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
         argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
   // Choose this constructor if it represents the closest match.
   if (typeDiffWeight < minTypeDiffWeight) {
      constructorToUse = candidate;
      argsHolderToUse = argsHolder;
      argsToUse = argsHolder.arguments;
      minTypeDiffWeight = typeDiffWeight;
      ambiguousConstructors = null;
   }
   else if(constructorToUse ! =null && typeDiffWeight == minTypeDiffWeight) {
      if (ambiguousConstructors == null) {
         ambiguousConstructors = newLinkedHashSet<>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); }}Copy the code

The long code above is to get the constructor that best matches the number and type of arguments

// Cache parsed constructors and arguments to prevent them from being parsed again the next time they are used
if (explicitArgs == null&& argsHolderToUse ! =null) {
   argsHolderToUse.storeCache(mbd, constructorToUse);
}
Copy the code
// Call the constructor to create the instance, set it to bw, and returnAssert.state(argsToUse ! =null."Unresolved constructor arguments");
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
Copy the code

Then go to the InstantiationStrategy class and view the called interface:

// Instantiate the bean object with the specified constructor
Object instantiate(RootBeanDefinition bd, @NullableString beanName, BeanFactory owner, Constructor<? > ctor, Object... args) throws BeansException;
Copy the code

Let’s look at the implementation:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
      finalConstructor<? > ctor, Object... args) {

   // If the bean does not have method overrides, use newInstance to instantiate it
   // Otherwise use cglib instantiation
   if(! bd.hasMethodOverrides()) {if(System.getSecurityManager() ! =null) {
         // use own privileged to change accessibility (when security is on)
         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            ReflectionUtils.makeAccessible(ctor);
            return null;
         });
      }
      return BeanUtils.instantiateClass(ctor, args);
   }
   else {
      returninstantiateWithMethodInjection(bd, beanName, owner, ctor, args); }}Copy the code

Look at BeanUtils. InstantiateClass method:

try {
   ReflectionUtils.makeAccessible(ctor);
   if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
      return KotlinDelegate.instantiateClass(ctor, args);
   }
   else{ Class<? >[] parameterTypes = ctor.getParameterTypes(); Assert.isTrue(args.length <= parameterTypes.length,"Can't specify more arguments than constructor parameters");
      Object[] argsWithDefaultValues = new Object[args.length];
      for (int i = 0 ; i < args.length; i++) {
         if (args[i] == null) { Class<? > parameterType = parameterTypes[i]; argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) :null);
         }
         else{ argsWithDefaultValues[i] = args[i]; }}returnctor.newInstance(argsWithDefaultValues); }}Copy the code

If you use additional will enter CglibSubclassingInstantiationStrategy class:

Class<? > subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
   instance = BeanUtils.instantiateClass(subclass);
}
else {
   try{ Constructor<? > enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes()); instance = enhancedSubclassConstructor.newInstance(args); }catch (Exception ex) {
      throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
            "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex); }}// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
      new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
      new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
Copy the code

Summary steps:

  1. The BeanWrapperImpl object is created, then initialized, the ConversionService type converter is set, and a custom property editor is registered
  2. Try to get the constructor and parameters, if they are specified by getBean, otherwise get them from the bean definition. The parsed constructors and parameters are first obtained from the bean definition, and if they have not been parsed, they are parsed
  3. Gets all matched constructors, if the collection of constructors chosenCtors is specified directly. If only one constructor is currently available, and getBean has no parameters specified and cannot be retrieved from the bean definition, then this constructor is called for instance creation
  4. The previous step, if not instantiated, starts by determining the minimum number of arguments, finding a constructor whose number of arguments is greater than or equal to it, and using weights to find the constructor that best matches it
  5. Finally, instantiate a bean instance using newInstance or cglib

In short, find a matching constructor, inject it if it has arguments, and then call that constructor to instantiate a bean

InstantiateBean method

Instantiate using the default no-argument constructor. Here’s the code:

/** * instantiates bean. * using the default no-argument constructor@param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @return a BeanWrapper for the new instance
 */
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
   try {
      Object beanInstance;
      // Permission validation
      if(System.getSecurityManager() ! =null) {
         // Get the InstantiationStrategy object and call the instantiate method to create the instance object
         beanInstance = AccessController.doPrivileged(
               (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
               getAccessControlContext());
      }
      else {
         // Get the InstantiationStrategy object and call the instantiate method to create the instance object
         beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
      }
      // Save the instantiated bean
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      // Initialize BeanWrapper
      initBeanWrapper(bw);
      return bw;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); }}Copy the code

Look at the SimpleInstantiationStrategy instantiate class methods:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
   // Don't override the class with CGLIB if no overrides.
   // If there is no method override, use reflection to instantiate
   if(! bd.hasMethodOverrides()) { Constructor<? > constructorToUse;/ / lock
      synchronized (bd.constructorArgumentLock) {
         // Try to get the parsed constructor from the bean definitionconstructorToUse = (Constructor<? >) bd.resolvedConstructorOrFactoryMethod;// If null, the default constructor is used
         if (constructorToUse == null) {
            / / for the class
            finalClass<? > clazz = bd.getBeanClass();// Throw an exception if the class is an interface
            if (clazz.isInterface()) {
               throw new BeanInstantiationException(clazz, "Specified class is an interface");
            }
            try {
               if(System.getSecurityManager() ! =null) {
                 // Get the constructor from clazzconstructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<? >>) clazz::getDeclaredConstructor); }else {
                  // Get the default constructor
                  constructorToUse = clazz.getDeclaredConstructor();
               }
               / / set resolvedConstructorOrFactoryMethod, namely the constructor has been parsed
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
            catch (Throwable ex) {
               throw new BeanInstantiationException(clazz, "No default constructor found", ex); }}}// Instantiate by reflection
      return BeanUtils.instantiateClass(constructorToUse);
   }
   else {
      // Must generate CGLIB subclass.
      Generate a subclass object from CGLIB
      returninstantiateWithMethodInjection(bd, beanName, owner); }}Copy the code

Summary steps:

  1. First see if there is a method to override, and if not, use reflection to instantiate
  2. If no parsed constructor is found, the default constructor is used
  3. The default constructor instantiates the bean object
  4. If method overrides exist, a subclass object is generated using CGLIB

Ok, to this whole bean create process source code, have looked almost, if there is an error please correct, thank you!