BeanFactory.getBean of Srping Source

This article is about source parsing for Srping's BeanFactory.getBean. If this is your first look, first look at XMLBeanFactory parsing: https://blog.csdn.net/qq_3025... To better understand Spring's registration principles, this blog is a step-by-step look at how spring implements getBean source code. Spring version is 5.X. The source code has been commented on each line to make it easier for readers to learn.**

GItHub:https://github.com/lantaoGitH...

  • Say nothing more. Let's look directly at the source code:
package org.springframework.lantao;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class XmlBeanFactoryTest {

    public static void main(String[] args) {
        ClassPathResource classPathResource = new ClassPathResource("spring-bean.xml");
        BeanFactory beanFactory = new XmlBeanFactory(classPathResource);
        UserBean userBean = (UserBean) beanFactory.getBean("userBean");
        System.out.println(userBean.getName());

    }
}

XMLBeanFactory parsing goes beyond that. If you haven't seen it, you can go to my last article and look directly at BeanFactory.getBean()

/**
 * Return an instance, which may be shared or independent, of the specified bean.
 * @param name the name of the bean to retrieve
 * @param requiredType the required type of the bean to retrieve
 * @param args arguments to use when creating a bean instance using explicit arguments
 * (only applied when creating a new instance as opposed to retrieving an existing one)
 * @param typeCheckOnly whether the instance is obtained for a type check,
 * not for actual use
 * @return an instance of the bean
 * @throws BeansException if the bean could not be created
 */
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    //Get instance name
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    // Check for instances in the singleton cache
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // Prototype circular reference throws an exception
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        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) parentBeanFactory.getBean(nameToLookup, args);
            }else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }
        if (!typeCheckOnly) {
            // Marks the specified bean as created (or about to be created).This allows the bean factory to optimize its cache so that specified beans can be created repeatedly
            markBeanAsCreated(beanName);
        }

        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

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

            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isTraceEnabled()) {
                logger.trace("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

doGetBean has a long source, so what does it do?

1: Transform the corresponding beanname, which many people may not understand. The incoming beanName should not be beanName. In fact, the incoming BeanFactory may be a BeanFactory or an alias. If it is a BeanFactory, remove its modifiers, such as the incoming&aa, it will be converted to aa, but if the incoming alias is an alias,To take the final beanName corresponding to alias, for example, if alias A points to beans of B, return the beanName of B. If alias A points to alias B and alias B points to C, return the BeanName of C.

2: Check if there is an instance in the singleton, it will be fetched from the cache first, which will be explained in detail below;

3: Determine if there is a circular dependency on the prototype instance, such as B in A and A in B. In this case, only the singleton mode will attempt to create, because the singleton mode will expose the instance earlier. In the presence of cache, the prototype mode is not allowed and the class is throwing an exception.

4: Get the bean through the parent BeanFactory;

5: Mark the specified beans as created (or about to be created).This allows the bean factory to optimize its cache

6: Get the RootBeanDefinition, which registers the beans in the beanDefinitionMap when the XmlBeanFactory parses, where is get in the beanDefinitionMap, throws the bean not found ing exception if it does not exist, and converts the GenericBeanDefinition to RootBeanDefinition because the GenericBeanDefinition is saved;

7: Check if the BeanDefinition is abstract and if it is thrown, the bean is Aastract exception;

8: Check the dependencies to ensure that the beans on which the beans depend are initialized. First of all, understand that depend-on is used to indicate that the instantiation of one bean A depends on the instantiation of another bean B, but A does not need to hold an object of B, so depend-on is not needed if needed. Don't understand to read this article

9: Determine whether a bean is of type single or proptotype, create a bean accordingly, or do not specify a scope. The most common method is getObjectForBeanInstance, which will be followed by a bit of parsing of its source code.

  • Next let's look at Singleton Cache Acquisition:
/**
 * Return the (raw) singleton object registered under the given name.
 * <p>Checks already instantiated singletons and also allows for an early
 * reference to a currently created singleton (resolving a circular reference).
 * @param beanName the name of the bean to look for
 * @param allowEarlyReference whether early references should be created or not
 * @return the registered singleton object, or {@code null} if none found
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    //Check that the instance isSingletonCurrentlyInCreation exists in the cache and that the instance is being created
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        //Lock and process the global variable singletonObjects if the instance in the cache is null
        synchronized (this.singletonObjects) {
            //Attempt to get beans from earlySingletonObjects (beanFactory created with early exposure)
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                //Attempt to get beanFactory from singletonFactories
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //Return the obtained bean
                    singletonObject = singletonFactory.getObject();
                    //Increase Cache
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    //Delete Cache
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

First, the singleton is only allowed to be created once and supports resolving circular dependencies. The first step is to get the singleton from the singletonObjectsMap. If it does not exist, then use singletonsCurrentlyInCreation to determine if the current bean is created or, if so, from the earlier exposed MapearlySingletonObjects.If it still doesn't exist, get the BeanFactory in singletonFactories, return it through getBean, and end it, the cache doesn't exist, it has to be recreated;

  • Next, look at isPrototypeCurrentlyInCreation
/**
 * Return whether the specified prototype bean is currently in creation
 * (within the current thread).
 * @param beanName the name of the bean
 */
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    return (curVal != null &&
            (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}

Here we determine if there is a circular dependency on the prototype instance, such as B in A and A in B. In this case, only the singleton mode will attempt to create it, because the singleton mode will expose the instance earlier. In the presence of the cache, the prototype mode is not allowed and the class is throwing an exception that is being created

  • markBeanAsCreated method source code:
if (!typeCheckOnly) {
        // Marks the specified bean as created (or about to be created).This allows the bean factory to optimize its cache
        markBeanAsCreated(beanName);
}

protected void markBeanAsCreated(String beanName) {
    if (!this.alreadyCreated.contains(beanName)) {
        synchronized (this.mergedBeanDefinitions) {
            if (!this.alreadyCreated.contains(beanName)) {
                // Let the bean definition get re-merged now that we're actually creating
                // the bean... just in case some of its metadata changed in the meantime.
                clearMergedBeanDefinition(beanName);
                this.alreadyCreated.add(beanName);
            }
        }
    }
}

As you can see from the above source code, the meaning of this code is that the specified beans are marked as already created or about to be created; in the clearMergedBeanDefinition method, if no tagged beans are being created, BeanDefinnation will be deleted and re-created later;

  • Continue with the getMergedLocalBeanDefinition source code:
/**
 * Return a merged RootBeanDefinition, traversing the parent bean definition
 * if the specified bean corresponds to a child bean definition.
 * @param beanName the name of the bean to retrieve the merged definition for
 * @return a (potentially merged) RootBeanDefinition for the given bean
 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
 * @throws BeanDefinitionStoreException in case of an invalid bean definition
 */
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    // Quick check on the concurrent map first, with minimal locking.
    RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
    if (mbd != null) {
        return mbd;
    }
    return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

In the getBeanDefinition method, spring is the BeanDefinition at the time of registration obtained directly from the beanDefinitionMap in the DefaultListAbleBeanFactory;

/**
 * Return a RootBeanDefinition for the given bean, by merging with the
 * parent if the given bean's definition is a child bean definition.
 * @param beanName the name of the bean definition
 * @param bd the original bean definition (Root/ChildBeanDefinition)
 * @param containingBd the containing bean definition in case of inner bean,
 * or {@code null} in case of a top-level bean
 * @return a (potentially merged) RootBeanDefinition for the given bean
 * @throws BeanDefinitionStoreException in case of an invalid bean definition
 */
protected RootBeanDefinition getMergedBeanDefinition(
        String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
        throws BeanDefinitionStoreException {

    synchronized (this.mergedBeanDefinitions) {
        RootBeanDefinition mbd = null;

        // Check with full lock now in order to enforce the same merged instance.
        if (containingBd == null) {
            mbd = this.mergedBeanDefinitions.get(beanName);
        }

        if (mbd == null) {
            if (bd.getParentName() == null) {
                // Use copy of given root bean definition.
                if (bd instanceof RootBeanDefinition) {
                    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                }
                else {
                    mbd = new RootBeanDefinition(bd);
                }
            }
            else {
                // Child bean definition: needs to be merged with parent.
                BeanDefinition pbd;
                try {
                    String parentBeanName = transformedBeanName(bd.getParentName());
                    if (!beanName.equals(parentBeanName)) {
                        pbd = getMergedBeanDefinition(parentBeanName);
                    }
                    else {
                        BeanFactory parent = getParentBeanFactory();
                        if (parent instanceof ConfigurableBeanFactory) {
                            pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            throw new NoSuchBeanDefinitionException(parentBeanName,
                                    "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                    "': cannot be resolved without an AbstractBeanFactory parent");
                        }
                    }
                }
                catch (NoSuchBeanDefinitionException ex) {
                    throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                            "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                }
                // Deep copy with overridden values.
                mbd = new RootBeanDefinition(pbd);
                mbd.overrideFrom(bd);
            }

            // Set default singleton scope, if not configured before.
            if (!StringUtils.hasLength(mbd.getScope())) {
                mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
            }

            // A bean contained in a non-singleton bean cannot be a singleton itself.
            // Let's correct this on the fly here, since this might be the result of
            // parent-child merging for the outer bean, in which case the original inner bean
            // definition will not have inherited the merged outer bean's singleton status.
            if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                mbd.setScope(containingBd.getScope());
            }

            // Cache the merged bean definition for the time being
            // (it might still get re-merged later on in order to pick up metadata changes)
            if (containingBd == null && isCacheBeanMetadata()) {
                this.mergedBeanDefinitions.put(beanName, mbd);
            }
        }
        return mbd;
    }
}

There are a few things you do in the getMergedBeanDefinition method:

1: Get BeanDefinition first from mergedBeanDefinitions in the cache

2: Initialize RootBeanDefinition through a parametric construction method, where instantiation involves the Set operation of some parameters, not shown in the specific code, in the parametric construction method of AbstractBeanDefinition;

3: Specify the scope of the bean;

4: Add RootBeanDefinition to the cache mergedBeanDefinitions;

It's easy to instantiate, not to mention the specific DeBug.

  • Let's continue with the checkMergedBeanDefinition method:
/**
 * Check the given merged bean definition,
 * potentially throwing validation exceptions.
 * @param mbd the merged bean definition to check
 * @param beanName the name of the bean
 * @param args the arguments for bean creation, if any
 * @throws BeanDefinitionStoreException in case of validation failure
 */
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
        throws BeanDefinitionStoreException {

    if (mbd.isAbstract()) {
        throw new BeanIsAbstractException(beanName);
    }
}

The checkMergedBeanDefinition method is to determine if the BeanDefinition is Abstract, and if it throws a beanIsAbstractException, there are not many explanations here, as you've learned about java.

  • The next step is to look at the current Bean dependencies, which need to be instantiated first:
// Guarantee initialization of beans that the current bean depends on.
// Ensure that the beans on which the current beans depend are initialized.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dep : dependsOn) {
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        registerDependentBean(dep, beanName);
        try {
            getBean(dep);
            }
            catch (NoSuchBeanDefinitionException ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                }
        }
}

In this method, if the current Bean has a dependency, it will go to GetBean's dependency first, ensuring that all the dependencies of the current Bean have been initialized and available, getBean is not unfamiliar to everyone, it is the getBean of BeanFactory;

  • Let's look at the creation process singleton for bean s:
// Create bean instance.
// Create a bean instance
if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
    try {
        return createBean(beanName, mbd, args);
    }
    catch (BeansException ex) {
        destroySingleton(beanName);
                throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

The above code is one of the main methods for creating beans, first calling getSingleton, then executing the createBean method with lambda, which in turn calls the getObjectForBeanInstance method.

  • First let's look at createBean and then at the getSingleton method:
/**
 * Central method of this class: 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;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    // Locking classes resolves classes based on the class attribute or className
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides.
    try {
        // Method Injection Preparation
        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 an opportunity to return a proxy instead of a target bean instance
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        // Instantiation Creation
        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);
    }
}

What the above code does:

1: Resolve the class, if there is a beanClass in the BeanDefinition, it will be returned directly, otherwise it needs to be loaded through ClassLoader, the code will not be sent, you can look at the source code yourself;

2: Method injection, That's how lookup-method is injected, so let's not go into any more details here. Read the article again.

3: spring's original explanation is to give BeanPostProcessors an opportunity to return a proxy instead of a target bean instance, involving Aop's proxy, which will be explained in more detail in subsequent articles.

4: Call doCreateBean to create, let's look directly at the doCreateBean method:

  • doCreateBean method:
/**
 * Actually create the specified bean. Pre-creation processing has already happened
 * at this point, e.g. checking  {@code postProcessBeforeInstantiation} callbacks.
 * <p>Differentiates between default bean instantiation, use of a
 * factory method, and autowiring a constructor.
 * @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
 * @see #instantiateBean
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 */
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        //Create an instance, such as a factory, using the appropriate policy
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // Whether to expose beforehand, singletons &allow circular dependencies &singletonsCurrentlyInCreation currently being created is created in DefaultSingletonBeanRegistry 225 line, recording that beans are being created before beans are created
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        // Join the cache before the bean s are instantiated, and the singleton supports circular dependency
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // Complementing beans, property injection, bean dependency
        populateBean(beanName, mbd, instanceWrapper);
        //Initialization method invoked
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        //earlySingletonReference is no longer empty when checking for circular dependencies
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(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 " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    return exposedObject;
}

The process of creating bean s is described in the code above, but the real createBean is not the same. In the createBeanInstance, let's first look at what the CreateBeann method does:

1: Create an instance createBeanInstance method using the corresponding policy;

2: Determine whether exposure is premature if (singletons & allow circular dependencies - singletons CurrentlyInCreation is currently being created in DefaultSingletonBeanRegistry 225 line, beans are being created in record before beans are created), if necessary call the addSingletonFactory method to join the beans before they are instantiatedIn the cache, the singleton supports circular dependency;

3: complement beans, attribute injection, bean dependency; initialize ByName, ByType dependencies and register dependent beans;

4: Initialization method is called;

5: Handling dependencies;

  • Take a look at the createBeanInstance method:
/**
 * Create a new instance for the specified bean, using an appropriate instantiation strategy:
 * factory method, constructor autowiring, or simple instantiation.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return a BeanWrapper for the new instance
 * @see #obtainFromSupplier
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 * @see #instantiateBean
 */
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    // Resolve class
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    //Ensure that the class is not empty and that access is public
    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());
    }
    //A special callback method configured to create bean s from this callback
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    // If factory mode is not empty, use function factory mode to resolve
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // A class may have more than one constructor, so Spring determines which constructor to call based on the number and type of parameters
    // After creating an instance using the constructor, Spring saves the constructor or factory methods that are determined after parsing in the cache, avoiding parsing again when the same bean s are created again
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            //Determine if the constructor or factory method is null
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                //Constructor that has resolved class
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    if (resolved) {
        if (autowireNecessary) {
            //Constructor Auto Injection
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            //Use default constructor
            return instantiateBean(beanName, mbd);
        }
    }

    // Constructors need to be resolved and determined based on parameters
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // Preferred constructors for default construction?
    // Preferred constructor for default construction?
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
    }
    // No special handling: simply use no-arg constructor.
    // Use default constructor
    return instantiateBean(beanName, mbd);
}

The above methods:

1: parse class;

2: If there is a Supplier callback, call obtainFromSupplier() to initialize, and return directly if it is not equal to null;

3: If the factory mode is not empty, use the function factory mode to resolve;

4: Constructor autowireConstructor

5: Default constructor instantiateBean

  • Let's first look at the use of the Supplier callback:
//A special callback method configured to create bean s from this callback
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
    return obtainFromSupplier(instanceSupplier, beanName);
}
/**
 * Obtain a bean instance from the given supplier.
 * @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;

    String outerBean = this.currentlyCreatedBean.get();
    this.currentlyCreatedBean.set(beanName);
    try {
        instance = instanceSupplier.get();
    }
    finally {
        if (outerBean != null) {
            this.currentlyCreatedBean.set(outerBean);
        }
        else {
            this.currentlyCreatedBean.remove();
        }
    }

    if (instance == null) {
        instance = new NullBean();
    }
    BeanWrapper bw = new BeanWrapperImpl(instance);
    initBeanWrapper(bw);
    return bw;
}
/**
 * Represents a supplier of results.
 *
 * <p>There is no requirement that a new or distinct result be returned each
 * time the supplier is invoked.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #get()}.
 *
 * @param <T> the type of results supplied by this supplier
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

Supplier is just a get method that returns a T-type object, somewhat like a factory method.What does this interface do?Callbacks are used to specify the creation of bean s, and if we set such callbacks, other constructors or factory methods will be useless.Where to set this parameter?Spring provides the appropriate setter methods as follows:

public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
    this.instanceSupplier = instanceSupplier;
}

This method is a method in the AbsTractBeanDefinition class that is called when the RootBeanDefinition is initialized; in the protected AbstractBeanDefinition(BeanDefinition original) method of the source code;

  • Start parsing the factory pattern instantiation Bean below, followed by the constructor and default construct instance methods.....
public BeanWrapper instantiateUsingFactoryMethod(
            String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

    // Instantiate BeanWrapperImpl
    BeanWrapperImpl bw = new BeanWrapperImpl();
    //Initialize BeanWrapperImpl
    this.beanFactory.initBeanWrapper(bw);

    Object factoryBean;
    Class<?> factoryClass;
    boolean isStatic;

    // Get Factory Bean Instantiate FactoryBean here using FactoryBean County
    // The factory name is not empty. Processing as follows
    String factoryBeanName = mbd.getFactoryBeanName();
    if (factoryBeanName != null) {
        if (factoryBeanName.equals(beanName)) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "factory-bean reference points back to the same bean definition");
        }
        factoryBean = this.beanFactory.getBean(factoryBeanName);
        if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
            throw new ImplicitlyAppearedSingletonException();
        }
        factoryClass = factoryBean.getClass();
        isStatic = false;
    }
    else {
        // If the factory name is empty, it may be a static factory
        // It's a static factory method on the bean class.
        // Factory-method factory-metohd can be used here to invoke factory work without invoking a function factory class instance, but not static.
        if (!mbd.hasBeanClass()) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "bean definition declares neither a bean class nor a factory-bean reference");
        }
        factoryBean = null;
        factoryClass = mbd.getBeanClass();
        isStatic = true;
    }

    // Factory method to be used
    Method factoryMethodToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    //Factory parameters to be used
    Object[] argsToUse = null;


    // Parameters for factory method
    // If a construction parameter is specified, use it directly
    // Method parameters are specified when calling the getBean method
    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    }
    else {
        // If not specified, try parsing from the configuration file
        Object[] argsToResolve = null;
        synchronized (mbd.constructorArgumentLock) {
            // Get a constructor or factory method
            factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
            if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                // Get construction parameters
                argsToUse = mbd.resolvedConstructorArguments;
                if (argsToUse == null) {
                    // Get Package Visible Fields for Constructor Parameters
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }
        if (argsToResolve != null) {
            // If present in the cache, parse the parameters stored in BeanDefinition
            // If the constructor A (int, int) of a given method is used, the ("1", "1") in the configuration file will be converted to (1,1)
            // The value in the cache may be the original value or the final value
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
        }
    }

    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.
        // The method for determining the factory is required. Try all methods with this name to see if they match the given parameters.

        // Gets the full class name of the factory method
        factoryClass = ClassUtils.getUserClass(factoryClass);

        // Retrieve all methods, here is filtering the methods
        Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
        List<Method> candidateList = new ArrayList<>();
        for (Method candidate : rawCandidates) {
            // If static and factory method, add to candidateSet
            if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                candidateList.add(candidate);
            }
        }

        // If the static method directly initializes the return for an &getBean parameter null &without a constructor value
        if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
            Method uniqueCandidate = candidateList.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));
                return bw;
            }
        }

        Method[] candidates = candidateList.toArray(new Method[0]);
        // Sort Constructor
        // Public constructor preference parameter number descending, non-public constructor parameter number descending
        AutowireUtils.sortFactoryMethods(candidates);

        ConstructorArgumentValues resolvedValues = null;
        boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
        int minTypeDiffWeight = Integer.MAX_VALUE;
        Set<Method> ambiguousFactoryMethods = null;

        int minNrOfArgs;
        if (explicitArgs != null) {
            minNrOfArgs = explicitArgs.length;
        }
        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.

            // Determine if there are construction parameter values in BeanDefinition
            // getBean() does not pass parameters, so you need to resolve the parameters that are saved in the BeanDefinition constructor
            if (mbd.hasConstructorArgumentValues()) {
                // Get construction parameter values
                ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                resolvedValues = new ConstructorArgumentValues();
                // Parameters of the analytic constructor
                minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
            }
            else {
                minNrOfArgs = 0;
            }
        }

        LinkedList<UnsatisfiedDependencyException> causes = null;

        // The loop method finds the matching one
        for (Method candidate : candidates) {

            // Get Method Parameters
            Class<?>[] paramTypes = candidate.getParameterTypes();

            if (paramTypes.length >= minNrOfArgs) {
                ArgumentsHolder argsHolder;
                // Parameters given by getbean s
                if (explicitArgs != null) {
                    // Explicit arguments given -> arguments length must match exactly.
                    // Parameter mismatch method skipped
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }
                    // Create parameter holders from parameters
                    argsHolder = new ArgumentsHolder(explicitArgs);
                }
                else {
                    // Resolved constructor arguments: type conversion and/or autowiring necessary.
                    try {
                        String[] paramNames = null;
                        // Get the ParameterNameDiscoverer object
                        // ParameterNameDiscoverer is an interface for parsing method and constructor parameter names and is a parameter name detector
                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                        if (pnd != null) {
                            // Gets the parameter name of the specified constructor
                            paramNames = pnd.getParameterNames(candidate);
                        }

                        //Create a parameter holder object with parsed constructor parameter values
                        argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
                                    paramTypes, paramNames, candidate, autowiring, candidates.length == 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;
                    }
                }


                // isLenientConstructorResolution determines whether the constructor is parsed in a relaxed or strict mode
                // Strict pattern: when parsing a constructor, all must match, otherwise an exception is thrown
                // Loose mode: Match using the closest mode
                // typeDiffWeight: Type difference weight
                int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                // Choose this factory method if it represents the closest match.
                //  Represents the closest type match, then chooses as the constructor
                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).
                else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
                        !mbd.isLenientConstructorResolution() &&
                        paramTypes.length == factoryMethodToUse.getParameterCount() &&
                        !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
                    if (ambiguousFactoryMethods == null) {
                        ambiguousFactoryMethods = new LinkedHashSet<>();
                        ambiguousFactoryMethods.add(factoryMethodToUse);
                    }
                    ambiguousFactoryMethods.add(candidate);
                }
            }
        }

        // No factory method to execute, throw exception
        if (factoryMethodToUse == null) {
            if (causes != null) {
                UnsatisfiedDependencyException ex = causes.removeLast();
                for (Exception cause : causes) {
                    this.beanFactory.onSuppressedException(cause);
                }
                throw ex;
            }
            List<String> argTypes = new ArrayList<>(minNrOfArgs);
            if (explicitArgs != null) {
                for (Object arg : explicitArgs) {
                    argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
                }
            }
            else if (resolvedValues != null) {
                Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
                    valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
                valueHolders.addAll(resolvedValues.getGenericArgumentValues());
                for (ValueHolder value : valueHolders) {
                    String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :                                (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
                        argTypes.add(argType);
                }
            }
            String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "No matching factory method found: " +
                        (mbd.getFactoryBeanName() != null ?
                            "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
                        "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
                        "Check that a method with the specified name " +
                        (minNrOfArgs > 0 ? "and arguments " : "") +
                        "exists and that it is " +
                        (isStatic ? "static" : "non-static") + ".");
            }
            else if (void.class == factoryMethodToUse.getReturnType()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Invalid factory method '" + mbd.getFactoryMethodName() +
                        "': needs to have a non-void return type!");
            }
            else if (ambiguousFactoryMethods != null) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Ambiguous factory method matches found in bean '" + beanName + "' " +
                        "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
                        ambiguousFactoryMethods);
        }

        if (explicitArgs == null && argsHolderToUse != null) {
            // Specify factory method
            mbd.factoryMethodToIntrospect = factoryMethodToUse;
            // Add parsed constructor to cache
            argsHolderToUse.storeCache(mbd, factoryMethodToUse);
        }
    }

    Assert.state(argsToUse != null, "Unresolved factory method arguments");
    bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
    return bw;
}

The above code, how to say, why do you write it all together, why don't you write it individually, each method clearly does what, to see this method requires perseverance, the reader will take a good look.... Let's see what this method does first:

1: First instantiate BeanWrapperImpl

2: Initialize BeanWrapperImpl

3: Get FactoryBean Name, if you don't know it before you look here factory-bean and factory-mothod Click , here you will determine if factoryBeannName is null, if not initialize the factory beans, the code is reflected in factoryBean = this.beanFactory.getBean(factoryBeanName), otherwise it must be a static-modified factory method that can be called directly;

4: Get the construction or factory method in the cache, and construct the parameters, explaining them online:;

  • constructorArgumentLock: Constructs the lock used by the cache;
  • resolvedConstructorOrFactoryMethod: A constructor or factory method;
  • resolvedConstructorArguments: Construction parameters

If the cache exists, you need to call the resolvePreparedArguments() method to convert it, because the value in the cache may or may not be the final value, such as type 1 in our constructor, but the original parameter type may be type 1 in String, so even ifConstruct parameters derived from the cache also require a type conversion to ensure that the parameter types correspond exactly.

5: If the parameters in the cache or uploaded do not have to be parsed, all the methods need to be obtained by reflection, and if the qualified static method is just one and no method parameters have been constructed, the return is initialized directly; the code is as follows:

// If the static method directly initializes the return for an &getBean parameter null &without a constructor value
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
    Method uniqueCandidate = candidateList.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));
    return bw;
    }
}

6: If the display provides parameters (explicitArgs!= null), use them directly, otherwise you need to get the ConstructorArgumentValues value and parse the constructor, which is more complex, and suggest debug for the reader;

7: Cycle through matches until a matching constructor is found; throw an exception if not found, no function is available; code as follows:

// The loop method finds the matching one
            for (Method candidate : candidates) {

                // Get Method Parameters
                Class<?>[] paramTypes = candidate.getParameterTypes();

                if (paramTypes.length >= minNrOfArgs) {
                    ArgumentsHolder argsHolder;
                    // Parameters given by getbean s
                    if (explicitArgs != null) {
                        // Explicit arguments given -> arguments length must match exactly.
                        // Parameter mismatch method skipped
                        if (paramTypes.length != explicitArgs.length) {
                            continue;
                        }
                        // Create parameter holders from parameters
                        argsHolder = new ArgumentsHolder(explicitArgs);
                    }
                    else {
                        // Resolved constructor arguments: type conversion and/or autowiring necessary.
                        try {
                            String[] paramNames = null;
                            // Get the ParameterNameDiscoverer object
                            // ParameterNameDiscoverer is an interface for parsing method and constructor parameter names and is a parameter name detector
                            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                            if (pnd != null) {
                                // Gets the parameter name of the specified constructor
                                paramNames = pnd.getParameterNames(candidate);
                            }

                            //Create a parameter holder object with parsed constructor parameter values
                            argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
                                    paramTypes, paramNames, candidate, autowiring, candidates.length == 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;
                        }
                    }


                    // isLenientConstructorResolution determines whether the constructor is parsed in a relaxed or strict mode
                    // Strict pattern: when parsing a constructor, all must match, otherwise an exception is thrown
                    // Loose mode: Match using the closest mode
                    // typeDiffWeight: Type difference weight
                    int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                    // Choose this factory method if it represents the closest match.
                    //  Represents the closest type match, then chooses as the constructor
                    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).
                    else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
                            !mbd.isLenientConstructorResolution() &&
                            paramTypes.length == factoryMethodToUse.getParameterCount() &&
                            !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
                        if (ambiguousFactoryMethods == null) {
                            ambiguousFactoryMethods = new LinkedHashSet<>();
                            ambiguousFactoryMethods.add(factoryMethodToUse);
                        }
                        ambiguousFactoryMethods.add(candidate);
                    }
                }
            }

            // No factory method to execute, throw exception
            if (factoryMethodToUse == null) {
                if (causes != null) {
                    UnsatisfiedDependencyException ex = causes.removeLast();
                    for (Exception cause : causes) {
                        this.beanFactory.onSuppressedException(cause);
                    }
                    throw ex;
                }
                List<String> argTypes = new ArrayList<>(minNrOfArgs);
                if (explicitArgs != null) {
                    for (Object arg : explicitArgs) {
                        argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
                    }
                }
                else if (resolvedValues != null) {
                    Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
                    valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
                    valueHolders.addAll(resolvedValues.getGenericArgumentValues());
                    for (ValueHolder value : valueHolders) {
                        String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
                                (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
                        argTypes.add(argType);
                    }
                }
                String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "No matching factory method found: " +
                        (mbd.getFactoryBeanName() != null ?
                            "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
                        "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
                        "Check that a method with the specified name " +
                        (minNrOfArgs > 0 ? "and arguments " : "") +
                        "exists and that it is " +
                        (isStatic ? "static" : "non-static") + ".");
            }

8: Specify the factory method and add the parsed constructor information to the cache as follows:

if (explicitArgs == null && argsHolderToUse != null) {
        // Specify factory method
        mbd.factoryMethodToIntrospect = factoryMethodToUse;
        // Add parsed constructor to cache
        argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}

public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
        synchronized (mbd.constructorArgumentLock) {
            mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
            mbd.constructorArgumentsResolved = true;
            if (this.resolveNecessary) {
                mbd.preparedConstructorArguments = this.preparedArguments;
            }
            else {
                mbd.resolvedConstructorArguments = this.arguments;
            }
        }
}

10: Instantiate the Bean through reflection, source code:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
            @Nullable Object factoryBean, final Method factoryMethod, Object... args) {

    try {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                ReflectionUtils.makeAccessible(factoryMethod);
                return null;
            });
        }
        else {
            ReflectionUtils.makeAccessible(factoryMethod);
        }

        Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
        try {
            currentlyInvokedFactoryMethod.set(factoryMethod);
            // Using reflection
            Object result = factoryMethod.invoke(factoryBean, args);
            if (result == null) {
                result = new NullBean();
            }
            return result;
        }
        finally {
            if (priorInvokedFactoryMethod != null) {
                currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
            }
            else {
                currentlyInvokedFactoryMethod.remove();
            }
        }
    }
    catch (IllegalArgumentException ex) {
        throw new BeanInstantiationException(factoryMethod,
                "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
                "args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
    }
    catch (IllegalAccessException ex) {
        throw new BeanInstantiationException(factoryMethod,
                "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
    }
    catch (InvocationTargetException ex) {
        String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
        if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
                ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
            msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
                        "declaring the factory method as static for independence from its containing instance. " + msg;
        }
        throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
    }
}
  • The above factory mode instantiation Bean is not very detailed, try debug source to understand step by step, see the constructor instantiate autowireConstructor below

Both factory instantiation and constructor instantiation require the reader's own deBug to better understand what has been done below:

1: Instantiate BeanWrapperImpl

2: Initialize BeanWrapperImpl

3: Constructor parameters are used if getBean is passed in, otherwise parameter types need to be retrieved and parsed from the cache:

  • constructorArgumentLock: Constructs the lock used by the cache;
  • resolvedConstructorOrFactoryMethod: A constructor or factory method;
  • resolvedConstructorArguments: Construction parameters

The code is as follows:

Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
    //Get the parse constructor or factory method
    constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
    //Constructor or factory method is not empty & there are constructors (functions)
    if (constructorToUse != null && mbd.constructorArgumentsResolved) {
        // Found a cached constructor...
        argsToUse = mbd.resolvedConstructorArguments;
        if (argsToUse == null) {
            // Configure constructor parameters
            argsToResolve = mbd.preparedConstructorArguments;
            }
        }
    }
    if (argsToResolve != null) {
    // Parse parameter types, such as construction method A(int, int), by which ("1", "1") is converted to (1, 1)
    argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}

4: Parse the constructor, if there are uploads, use it, if not get it from the beanClass, and add the cache after parsing, the code is:

if (constructorToUse == null || argsToUse == null) {
        // Accepts the specified constructor, if any..
        Constructor<?>[] candidates = chosenCtors;
        if (candidates == null) {
            // Get from class
            Class<?> beanClass = mbd.getBeanClass();
            try {
                // Get the constructor from class to determine if it is public
                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);
            }
        }
        // Constructor value == null returns directly
        if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
            Constructor<?> uniqueCandidate = candidates[0];
            if (uniqueCandidate.getParameterCount() == 0) {
                synchronized (mbd.constructorArgumentLock) {
                    // Constructor or Factory Method
                    mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                    //Constructor Parameter Analysis
                    mbd.constructorArgumentsResolved = true;
                    // constructors parameters
                    mbd.resolvedConstructorArguments = EMPTY_ARGS;
                }
                bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
                return bw;
            }
        }

        // Constructor parameters need to be parsed
        boolean autowiring = (chosenCtors != null ||
                mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
        ConstructorArgumentValues resolvedValues = null;

        int minNrOfArgs;
        if (explicitArgs != null) {
            minNrOfArgs = explicitArgs.length;
        }
        else {
            ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
            resolvedValues = new ConstructorArgumentValues();
            // Analytic Constructor Parameters
            minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
        }

        AutowireUtils.sortConstructors(candidates);
        int minTypeDiffWeight = Integer.MAX_VALUE;
        Set<Constructor<?>> ambiguousConstructors = null;
        LinkedList<UnsatisfiedDependencyException> causes = null;

        for (Constructor<?> candidate : candidates) {
            //Get the construction method parameter type
            Class<?>[] paramTypes = candidate.getParameterTypes();

            if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
                // Already found greedy constructor that can be satisfied ->
                // do not look any further, there are only less greedy constructors left.
                // Terminates if an available constructor has been found or if the number of required parameters is less than the current number of functions
                break;
            }
            if (paramTypes.length < minNrOfArgs) {
                //Unequal number of parameters
                continue;
            }

            ConstructorResolver.ArgumentsHolder argsHolder;
            if (resolvedValues != null) {
                try {
                    // Get the parameter name from the comment
                    String[] paramNames = ConstructorResolver.ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
                    if (paramNames == null) {
                        // Parameter Name Exploration Period
                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                        if (pnd != null) {
                            //Get the parameters on the construction method
                            paramNames = pnd.getParameterNames(candidate);
                        }
                    }
                    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 {
                // Parametric construction
                // Explicit arguments given -> arguments length must match exactly.
                if (paramTypes.length != explicitArgs.length) {
                    continue;
                }
                argsHolder = new ConstructorResolver.ArgumentsHolder(explicitArgs);
            }

            // Determine whether there are uncertain constructs
            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 = new LinkedHashSet<>();
                    ambiguousConstructors.add(constructorToUse);
                }
                ambiguousConstructors.add(candidate);
            }
        }

        if (constructorToUse == null) {
            if (causes != null) {
                UnsatisfiedDependencyException ex = causes.removeLast();
                for (Exception cause : causes) {
                    this.beanFactory.onSuppressedException(cause);
                }
                throw ex;
            }
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Could not resolve matching constructor " +
                            "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
        }
        else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Ambiguous constructor matches found in bean '" + beanName + "' " +
                            "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
                            ambiguousConstructors);
        }

        if (explicitArgs == null && argsHolderToUse != null) {
            // Join Cache
            argsHolderToUse.storeCache(mbd, constructorToUse);
        }
    }

5: Instantiate Bean, Source:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
    final Constructor<?> ctor, Object... args) {
    // Create using reflection directly if lookuo or replace is not used
    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;
            });
        }
        // Create you directly using reflection
        return BeanUtils.instantiateClass(ctor, args);
    }
    else {
        return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
    }
}

  • Here's how the default constructor instantiate Bean instantiates beans:
/**
 * Instantiate the given bean using its default 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(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
            getInstantiationStrategy().instantiate(mbd, beanName, parent),
            getAccessControlContext());
        }
        else {
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // Don't override the class with CGLIB if no overrides.
    if (!bd.hasMethodOverrides()) {
        Constructor<?> constructorToUse;
        synchronized (bd.constructorArgumentLock) {
            //Get Constructor
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                // Get clazz
                final Class<?> clazz = bd.getBeanClass();
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    if (System.getSecurityManager() != null) {
                        constructorToUse = AccessController.doPrivileged(
                                (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                    }
                    else {
                        // Get Common Constructors
                        constructorToUse = clazz.getDeclaredConstructor();
                    }
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        // Instantiate class
        return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
        // Must generate CGLIB subclass.
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

The above code is for instantiating beans using the default constructor, which I won't go into much detail here; you've seen the code for instantiating beans using factory schemas and construction parameters, and it's easy to understand here; let's move on to the getSingleton method:

  • getSingleton method:
/**
 * Return the (raw) singleton object registered under the given name,
 * creating and registering a new one if none registered yet.
 * @param beanName the name of the bean
 * @param singletonFactory the ObjectFactory to lazily create the singleton
 * with, if necessary
 * @return the registered singleton object
 */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    // Lock, global variables need to be synchronized
    synchronized (this.singletonObjects) {
        //See if the singleton bean s were created in a country that was used directly
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {
                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 (logger.isDebugEnabled()) {
                logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
            }
            //Record load status Book 99 pages
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                //Delete Load State
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

Let's just say what this method does, as follows:

1: First, the global lock singletonObjects;

2: Check the existence of the cache and, if so, determine whether the acquired beans are in the destruction phase;

3: Use singletonsCurrentlyInCreation to record the loading status;

4: Use the ObjectFactory returned by the createBean method to get the bean and specify that this creation is a new singleton;

5: Delete the loading state in singletonsCurrentlyInCreation;

6: Add cache, code as follows:

/**
 * Add the given singleton object to the singleton cache of this factory.
 * <p>To be called for eager registration of singletons.
 * @param beanName the name of the bean
 * @param singletonObject the singleton object
 */
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, singletonObject);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

  • Next, take a look at the method getObjectForBeanInstance that getBean invokes most:
/**
 * Get the object for the given bean instance, either the bean
 * instance itself or its created object in case of a FactoryBean.
 * @param beanInstance the shared bean instance
 * @param name name that may include factory dereference prefix
 * @param beanName the canonical bean name
 * @param mbd the merged bean definition
 * @return the object to expose for the bean
 */
protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    // Validation fails if the specified name is factory-related (&prefix) and the beanInstance is not a FactoryBean class
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    //If we have an instance of a bean, it might be that the bean is a beanfactory, or if it is a FactoryBean we use it to create an instance, but if the user wants to get the factory instance directly instead of the corresponding instance of the factory's getObject method,
    //Then the incoming name should be prefixed with &
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd == null) {
        //Attempting to load an instance from the cache
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // Return bean instance from factory.
        // beanInstance must be FactoryBean
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        //Get the beanDefinition in the beanDefinitionMap, which is the Map at the time of registration
        if (mbd == null && containsBeanDefinition(beanName)) {
            // Convert GernericBeanDefinition saved during xml parsing to RootBeanDefinition
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        //Is it user defined, not the application itself
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

The above code has two judgements:

1: Throw a BeanIsNotAFactoryBean exception if the specified name is factory-related (&prefix) and the beanInstance type is not FactoryBean;

2: If the beanInstance is not a FactoryBean or the specified name is factory-related (&prefix), return the beanInstance directly;

These two conditions are well understood. The first one should be fine, if factory-related is specified and if the beanInstance class is FactoryBean or not throws an exception, the second one can understand that beanInstance returns directly if it is not FactoryBean, and the second one BeanFactoryUtils.isFactoryDereference(name) will never be true, because if this is true, the first condition will not throw an exception directly, so the code below handles that the beanInstrace is a BeanFactory, but the name passed in is not&name;

3: The code below is very simple. The mbd parameter is not null, it will only be null when the cache is acquired. Instead of explaining this, simply convert the BeanInstance type to FactoryBean<T> and call the getObjectFromFactoryBean method for getObject return.

4: FactoryBean doesn't understand this article, for example: https://blog.csdn.net/qq_3025...

summary

To summarize, the reason why caching is constantly used in getSinngnleton is that it is a singleton that does not allow duplicate creation. Let's focus on:

1: If it is a singleton, it is fetched from the cache first and not created by calling the getSingleton method;

2: Check if the bean is abstract

3: Ensure that the beans on which the current beans depend are initialized, if no dependencies are initialized first;

4: Get BeanDefinition, BeanDefinition is instantiated at the time of registration and stored in the cache, which is taken directly here to do a type conversion;

5: call the getSingleton method if it is a singleton, call the code block below isPrototype if it is a prototype, and use the default creation (prototype) if they are not;

6: The singletonsCurrentlyInCreation or prototypesCurrentlyInCreation will be used before and after the bean s are created to mark whether the class is being created for subsequent judgment;

7:The way bean s are instantiated, a judgment is made before an instance is created, if any, returned directly through the InstanceSupplier.et method, instantiateUsingFactoryMethod, autowireConstructor, default constructor instantiateBean, where the reader needs to see the sourceFocus of code,

8:Beans expose instances and increase caches before they are created, so that if someone else relies on them, they can fetch you directly from the cache and solve the circular dependency problem.

9: Injection of a bean's assignment property (populateBean method);

10: Initialization method called, initializeBean;

For 9 and 10, there is no detailed explanation in the code, but there are some comments in the source code, you can debug to see it by yourself is very simple, mainly too many, you know it was written separately early, very tired.... I don't know if you can see it as a reader;

The code is not easy. Please indicate the source when you transfer it: https://mp.csdn.net/postedit/...

Blog address: https://lantaogithub.github.io
Short Book: https://www.jianshu.com/u/bfb...
CSDN: https://blog.csdn.net/qq_3025...
Open Source China: https://my.oschina.net/u/3948555
Nuggets: https://juejin.im/user/5c8c6f...
Think no: https://segmentfault.com/u/qi...

Keywords: Java Spring github xml Attribute

Added by plugnz on Wed, 21 Aug 2019 06:01:12 +0300