Source code analysis of spring learning -- AbstractBeanFactory

Keywords: Java Attribute

AbstractBeanFactory

AbstractBeanFactory abstract class, inherited FactoryBeanRegistrySupport And realized. ConfigurableBeanFactory Interface.

Class structure

constant

// Parent class container
private BeanFactory parentBeanFactory;
// Class loader
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
// Temporary loader
private ClassLoader tempClassLoader;
// Metadata cache of bean
private boolean cacheBeanMetadata = true;
// Expression resolver of bean
private BeanExpressionResolver beanExpressionResolver;
// Type converter
private ConversionService conversionService;
// Attribute editor 
private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet<>(4);
// Attribute Editor for class
private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>(4);
// Type converter
private TypeConverter typeConverter;
// Add a string parser for embedded values, such as comment properties
private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();
// Post Processors 
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
// Is instantiaionawarebeanpostprocessors registered
private volatile boolean hasInstantiationAwareBeanPostProcessors;
// Whether DestructionAwareBeanPostProcessors are registered
private volatile boolean hasDestructionAwareBeanPostProcessors;
// Scope of action
private final Map<String, Scope> scopes = new LinkedHashMap<>(8);
// Provide security scope
private SecurityContextProvider securityContextProvider;
// Merged BeanDefinition
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
// Whether the bean instance has been created
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
// Local cache, multiple beans being created. The local thread is used here because the bean created by other threads does not conflict with the current thread
private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal<>("Prototype beans currently in creation");

Method analysis

AbstractBeanFactory

Constructor, the parent container can be passed in as a parameter

public AbstractBeanFactory() {
}

public AbstractBeanFactory(@Nullable BeanFactory parentBeanFactory) {
    this.parentBeanFactory = parentBeanFactory;
}

getBean

It's actually a method that calls doGetBean

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

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

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

    return doGetBean(name, requiredType, args, false);
}

doGetBean

doGetBean has four parameters:

  • Name: bean name
  • requiredType: returned type
  • args: construction parameters passed
  • typeCheckOnly: check type
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    //There are three ways to get the beanName: one is the original beanName, the other is the plus & and the other is the alias
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    // Has it been created
    Object sharedInstance = getSingleton(beanName);
    //It has been created, and there are no construction parameters. Enter this method. If there are construction parameters, go down, that is, do not get the bean, but directly create the bean
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            // If the bean is currently being created, throw an exception
            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 + "'");
            }
        }
        // If it's a normal bean, return it directly. If it's a FactoryBean, return its getObject
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {// No bean or multiple instances have been created
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // The bean that has created Prototype will loop reference and throw an exception
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // The parent container exists. There is no current beanName in the local area. Take it from the parent container.
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            // After processing, if you add &, add&
            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) {
            // typeCheckOnly is false, put beanName in alreadyCreated.
            markBeanAsCreated(beanName);
        }

        try {
            // Get BeanDefinition
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // Abstract class checking
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            // If there is a dependency, initialize the dependent bean first
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // Check whether there is circular dependency, a depends on b, b depends on a. Including transitive dependencies, such as a dependency b, b dependency c, c dependency a
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // Registration dependency
                    registerDependentBean(dep, beanName);
                    try {
                        // Initialize dependent bean s
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            // If it's a single case
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // Create bean
                        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;
                    }
                });
                // If it's a normal bean, return it directly. If it's a FactoryBean, return its getObject
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    // Add prototype currentlycreation, indicating that it is being created
                    beforePrototypeCreation(beanName);
                    //Create bean
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    // Remove prototypes currentlycreation, indicating that the creation is finished
                    afterPrototypeCreation(beanName);
                }
                // If it's a normal bean, return it directly. If it's a FactoryBean, return its getObject
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                // There are other corresponding scope policies to instantiate instead of single or multiple instances
                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.
    // Type checking
    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;
}

containsBean

Whether the bean has been created or defined, including the current container and the parent container

public boolean containsBean(String name) {
    String beanName = transformedBeanName(name);
    // Singleton bean created or include bean definition
    if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
        // If not & first, go straight back
        // If it starts with, judge whether it is a FactoryBean, and find it from the parent class
        return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
    }
    // Not found -> check parent.
    // The current container is not found. Go to the parent class
    BeanFactory parentBeanFactory = getParentBeanFactory();
    return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}

isSingleton

Specifies whether the beanName is a singleton, including ordinary beans and factorybeans, including the current container and the parent container

public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
    String beanName = transformedBeanName(name);
    // If it has been instantiated
    Object beanInstance = getSingleton(beanName, false);
    if (beanInstance != null) {
        if (beanInstance instanceof FactoryBean) {
            // It is of FactoryBean type, name should start with & or isSingleton method in FactoryBean returns true
            return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean<?>) beanInstance).isSingleton());
        }
        else {
            // If it's not a FactoryBean, name can't start with
            return !BeanFactoryUtils.isFactoryDereference(name);
        }
    }

    // No singleton instance found -> check bean definition.
    // If the current container has not been instantiated, go to the parent class to find
    BeanFactory parentBeanFactory = getParentBeanFactory();
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // No bean definition found in this factory -> delegate to parent.
        return parentBeanFactory.isSingleton(originalBeanName(name));
    }
    // There is no parent class. Judge whether it is a single instance according to the definition
    // Get the merged BeanDefinition
    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

    // In case of FactoryBean, return singleton status of created object if not a dereference.
    if (mbd.isSingleton()) {
        // If it is defined as a single ex amp le, judge whether it is a FactoryBean. If it is a FactoryBean, name is the beginning of &
        if (isFactoryBean(beanName, mbd)) {
            if (BeanFactoryUtils.isFactoryDereference(name)) {
                return true;
            }
            // If it is a single instance, but the name is not & at the beginning, get factoryBean again, and then judge whether it is a single instance
            FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
            return factoryBean.isSingleton();
        }
        else {
            // If it's not a FactoryBean, it can't be & start
            return !BeanFactoryUtils.isFactoryDereference(name);
        }
    }
    else {
        return false;
    }
}

isPrototype

Specifies whether the beanName is a multiple example, including ordinary beans and factorybeans, including the current container and the parent container

public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
    String beanName = transformedBeanName(name);
    // There is a parent container, and there is no definition of beanName. Search from the parent container
    BeanFactory parentBeanFactory = getParentBeanFactory();
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // No bean definition found in this factory -> delegate to parent.
        return parentBeanFactory.isPrototype(originalBeanName(name));
    }
    // No more lookups from the current container
    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    if (mbd.isPrototype()) {
        // In case of FactoryBean, return singleton status of created object if not a dereference.
        // If it is a normal bean, it returns true. If it starts with & and is a FactoryBean, it returns true
        return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName, mbd));
    }

    // Singleton or scoped - not a prototype.
    // However, FactoryBean may still produce a prototype object...
    // If it's not Prototype, and it's & beginning, and it's FactoryBean, FactoryBean is singleton, so it returns false
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        return false;
    }
    // If it is a FactoryBean, judge whether there is a Singleton or Prototype
    if (isFactoryBean(beanName, mbd)) {
        final FactoryBean<?> fb = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
        if (System.getSecurityManager() != null) {
            return AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
                    ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) || !fb.isSingleton()),
                    getAccessControlContext());
        }
        else {
            return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
                    !fb.isSingleton());
        }
    }
    else {
        return false;
    }
}

isTypeMatch

Whether the specified beanName matches the type

public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
        String beanName = transformedBeanName(name);

    // Check manually registered singletons.
    // Get single case
    Object beanInstance = getSingleton(beanName, false);
    // Is not empty and is not a NullBean type
    if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
        if (beanInstance instanceof FactoryBean) {
            if (!BeanFactoryUtils.isFactoryDereference(name)) {
                // No & first, get the getObjectType type of FactoryBean, and then compare
                Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);
                return (type != null && typeToMatch.isAssignableFrom(type));
            }
            else {
                // name is the beginning of & directly judge the type FactoryBean
                return typeToMatch.isInstance(beanInstance);
            }
        }
        // Normal bean without & start
        else if (!BeanFactoryUtils.isFactoryDereference(name)) {
            if (typeToMatch.isInstance(beanInstance)) {
                // Direct match for exposed instance?
                return true;
            }
            // Generic with definition of beanName
            else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) {
                // Generics potentially only match on the target class, not on the proxy...
                // Merge definition
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                Class<?> targetType = mbd.getTargetType();
                if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
                    // Check raw class match as well, making sure it's exposed on the proxy.
                    Class<?> classToMatch = typeToMatch.resolve();
                    if (classToMatch != null && !classToMatch.isInstance(beanInstance)) {
                        return false;
                    }
                    if (typeToMatch.isAssignableFrom(targetType)) {
                        return true;
                    }
                }
                ResolvableType resolvableType = mbd.targetType;
                if (resolvableType == null) {
                    resolvableType = mbd.factoryMethodReturnType;
                }
                return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType));
            }
        }
        return false;
    }
    // It has been created, but there is no bean definition, indicating that it is empty to register
    else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
        // null instance registered
        return false;
    }

    // No singleton instance found -> check bean definition.
    // Search from parent class
    BeanFactory parentBeanFactory = getParentBeanFactory();
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // No bean definition found in this factory -> delegate to parent.
        return parentBeanFactory.isTypeMatch(originalBeanName(name), typeToMatch);
    }

    // Retrieve corresponding bean definition.
    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

    Class<?> classToMatch = typeToMatch.resolve();
    if (classToMatch == null) {
        classToMatch = FactoryBean.class;
    }
    Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ?
            new Class<?>[] {classToMatch} : new Class<?>[] {FactoryBean.class, classToMatch});

    // Check decorated bean definition, if any: We assume it'll be easier
    // to determine the decorated bean's type than the proxy's type.
    BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
    if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
        RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
        Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd, typesToMatch);
        if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
            return typeToMatch.isAssignableFrom(targetClass);
        }
    }

    Class<?> beanType = predictBeanType(beanName, mbd, typesToMatch);
    if (beanType == null) {
        return false;
    }

    // Check bean class whether we're dealing with a FactoryBean.
    if (FactoryBean.class.isAssignableFrom(beanType)) {
        if (!BeanFactoryUtils.isFactoryDereference(name) && beanInstance == null) {
            // If it's a FactoryBean, we want to look at what it creates, not the factory class.
            beanType = getTypeForFactoryBean(beanName, mbd);
            if (beanType == null) {
                return false;
            }
        }
    }
    else if (BeanFactoryUtils.isFactoryDereference(name)) {
        // Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean
        // type but we nevertheless are being asked to dereference a FactoryBean...
        // Let's check the original bean class and proceed with it if it is a FactoryBean.
        beanType = predictBeanType(beanName, mbd, FactoryBean.class);
        if (beanType == null || !FactoryBean.class.isAssignableFrom(beanType)) {
            return false;
        }
    }

    ResolvableType resolvableType = mbd.targetType;
    if (resolvableType == null) {
        resolvableType = mbd.factoryMethodReturnType;
    }
    if (resolvableType != null && resolvableType.resolve() == beanType) {
        return typeToMatch.isAssignableFrom(resolvableType);
    }
    return typeToMatch.isAssignableFrom(beanType);
}

public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
    // After the type conversion, the above method is called.
    return isTypeMatch(name, ResolvableType.forRawClass(typeToMatch));
}

getType

Gets the type of the specified beanName

public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
    String beanName = transformedBeanName(name);

    // Check manually registered singletons.
    Object beanInstance = getSingleton(beanName, false);
    // Instantiated and not NullBean
    if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
        // If it is a FactoryBean and there is no &, the getObjectType type of FactoryBean is taken
        if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
            return getTypeForFactoryBean((FactoryBean<?>) beanInstance);
        }
        else {
            // Direct return type
            return beanInstance.getClass();
        }
    }

    // No singleton instance found -> check bean definition.
    // There is no instance. Check whether there is instantiation from the parent container
    BeanFactory parentBeanFactory = getParentBeanFactory();
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // No bean definition found in this factory -> delegate to parent.
        return parentBeanFactory.getType(originalBeanName(name));
    }
    // No instantiation, search from the definition
    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

    // Check decorated bean definition, if any: We assume it'll be easier
    // to determine the decorated bean's type than the proxy's type.
    BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
    if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
        RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
        Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd);
        if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
            return targetClass;
        }
    }

    Class<?> beanClass = predictBeanType(beanName, mbd);

    // Check bean class whether we're dealing with a FactoryBean.
    if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
        if (!BeanFactoryUtils.isFactoryDereference(name)) {
            // If it's a FactoryBean, we want to look at what it creates, not at the factory class.
            return getTypeForFactoryBean(beanName, mbd);
        }
        else {
            return beanClass;
        }
    }
    else {
        return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null);
    }
}

getAliases

public String[] getAliases(String name) {
    String beanName = transformedBeanName(name);
    List<String> aliases = new ArrayList<>();
    // If there is & add it back after parsing
    boolean factoryPrefix = name.startsWith(FACTORY_BEAN_PREFIX);
    String fullBeanName = beanName;
    if (factoryPrefix) {
        fullBeanName = FACTORY_BEAN_PREFIX + beanName;
    }
    if (!fullBeanName.equals(name)) {
        aliases.add(fullBeanName);
    }
    String[] retrievedAliases = super.getAliases(beanName);
    for (String retrievedAlias : retrievedAliases) {
        String alias = (factoryPrefix ? FACTORY_BEAN_PREFIX : "") + retrievedAlias;
        if (!alias.equals(name)) {
            aliases.add(alias);
        }
    }
    // No instantiation and no bean definition, search from the parent class
    if (!containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null) {
            aliases.addAll(Arrays.asList(parentBeanFactory.getAliases(fullBeanName)));
        }
    }
    return StringUtils.toStringArray(aliases);
}

getParentBeanFactory

Get parent container

public BeanFactory getParentBeanFactory() {
    return this.parentBeanFactory;
}

setParentBeanFactory

Set parent container

public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) {
    // Only one can be set and cannot be modified
    if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
        throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
    }
    this.parentBeanFactory = parentBeanFactory;
}

containsLocalBean

Whether the current container has the specified bean

public boolean containsLocalBean(String name) {
    String beanName = transformedBeanName(name);
    return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) &&
            (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName)));
}

setBeanClassLoader

getBeanClassLoader

Class loader, temporary loader

// Set class loader
public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) {
    this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader());
}
// Get class loader
public ClassLoader getBeanClassLoader() {
    return this.beanClassLoader;
}
// Set the temporary loader. If load time weaving is involved, only one temporary class loader is usually specified to ensure that the actual bean class is loaded as late as possible
public void setTempClassLoader(@Nullable ClassLoader tempClassLoader) {
    this.tempClassLoader = tempClassLoader;
}
// Get temporary loader
public ClassLoader getTempClassLoader() {
    return this.tempClassLoader;
}

setCacheBeanMetadata

isCacheBeanMetadata

The metadata cache of the bean, which is true by default. If it is false, every time you create a bean, you need to get information from the classloader

// Set whether to cache
public void setCacheBeanMetadata(boolean cacheBeanMetadata) {
    this.cacheBeanMetadata = cacheBeanMetadata;
}

// Get whether to cache
public boolean isCacheBeanMetadata() {
    return this.cacheBeanMetadata;
}

setBeanExpressionResolver

getBeanExpressionResolver

Expression resolver of bean

// Set up expression resolver
public void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver) {
    this.beanExpressionResolver = resolver;
}

// Get expression resolver
public BeanExpressionResolver getBeanExpressionResolver() {
    return this.beanExpressionResolver;
}

setConversionService

getConversionService

Type converter

// Set type converter
public void setConversionService(@Nullable ConversionService conversionService) {
    this.conversionService = conversionService;
}

// Get type converter
public ConversionService getConversionService() {
    return this.conversionService;
}

addPropertyEditorRegistrar

getPropertyEditorRegistrars

Attribute editor

// Add Attribute Editor
public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) {
    Assert.notNull(registrar, "PropertyEditorRegistrar must not be null");
    this.propertyEditorRegistrars.add(registrar);
}
// Get Attribute Editor
public Set<PropertyEditorRegistrar> getPropertyEditorRegistrars() {
    return this.propertyEditorRegistrars;
}

registerCustomEditor

Attribute Editor for class

// Register the Attribute Editor of a class
public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
    Assert.notNull(requiredType, "Required type must not be null");
    Assert.notNull(propertyEditorClass, "PropertyEditor class must not be null");
    this.customEditors.put(requiredType, propertyEditorClass);
}
// Attribute Editor for copy class
public void copyRegisteredEditorsTo(PropertyEditorRegistry registry) {
    registerCustomEditors(registry);
}
// Get the Attribute Editor of the class
public Map<Class<?>, Class<? extends PropertyEditor>> getCustomEditors() {
    return this.customEditors;
}

setTypeConverter

getCustomTypeConverter

getTypeConverter

Type converter

// Set type converter
public void setTypeConverter(TypeConverter typeConverter) {
    this.typeConverter = typeConverter;
}
// Get the custom type converter. Here, take the type converter directly
protected TypeConverter getCustomTypeConverter() {
    return this.typeConverter;
}
// Get type converter
public TypeConverter getTypeConverter() {
    TypeConverter customConverter = getCustomTypeConverter();
    if (customConverter != null) {
        return customConverter;
    }
    else {
        // Build default TypeConverter, registering custom editors.
        // Initializing a simpletypconverter without setting a value
        SimpleTypeConverter typeConverter = new SimpleTypeConverter();
        typeConverter.setConversionService(getConversionService());
        registerCustomEditors(typeConverter);
        return typeConverter;
    }
}

addEmbeddedValueResolver

hasEmbeddedValueResolver

resolveEmbeddedValue

Add a string parser for embedded values, such as comment properties

// Add to
public void addEmbeddedValueResolver(StringValueResolver valueResolver) {
    Assert.notNull(valueResolver, "StringValueResolver must not be null");
    this.embeddedValueResolvers.add(valueResolver);
}
// Whether there is
public boolean hasEmbeddedValueResolver() {
    return !this.embeddedValueResolvers.isEmpty();
}

// Resolve the given embedded value
public String resolveEmbeddedValue(@Nullable String value) {
    if (value == null) {
        return null;
    }
    String result = value;
    for (StringValueResolver resolver : this.embeddedValueResolvers) {
        result = resolver.resolveStringValue(result);
        if (result == null) {
            return null;
        }
    }
    return result;
}

addBeanPostProcessor

getBeanPostProcessorCount

getBeanPostProcessors

// Add post processor
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
    // Remove from old position, if any
    // Remove old, ensure order
    this.beanPostProcessors.remove(beanPostProcessor);
    // Track whether it is instantiation/destruction aware
    // If it is the following two types, the flag bit is set to true
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
        this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
        this.hasDestructionAwareBeanPostProcessors = true;
    }
    // Add to end of list
    this.beanPostProcessors.add(beanPostProcessor);
}
// Get the number of post processors
public int getBeanPostProcessorCount() {
    return this.beanPostProcessors.size();
}
// Get postprocessor
public List<BeanPostProcessor> getBeanPostProcessors() {
    return this.beanPostProcessors;
}

hasInstantiationAwareBeanPostProcessors

hasDestructionAwareBeanPostProcessors

These two values are set when addBeanPostProcessor

protected boolean hasInstantiationAwareBeanPostProcessors() {
    return this.hasInstantiationAwareBeanPostProcessors;
}
protected boolean hasDestructionAwareBeanPostProcessors() {
    return this.hasDestructionAwareBeanPostProcessors;
}

registerScope

getRegisteredScopeNames

getRegisteredScope

Scope of action

// Registration scope
public void registerScope(String scopeName, Scope scope) {
    Assert.notNull(scopeName, "Scope identifier must not be null");
    Assert.notNull(scope, "Scope must not be null");
    // Single case and multiple cases, re registration is not allowed
    if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
        throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
    }
    Scope previous = this.scopes.put(scopeName, scope);
    if (previous != null && previous != scope) {
        if (logger.isDebugEnabled()) {
            logger.debug("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]");
        }
    }
    else {
        if (logger.isTraceEnabled()) {
            logger.trace("Registering scope '" + scopeName + "' with implementation [" + scope + "]");
        }
    }
}
// Get scope, except for single and multiple cases, which will report an error when registering.
public String[] getRegisteredScopeNames() {
    return StringUtils.toStringArray(this.scopes.keySet());
}
// Get scope by name
public Scope getRegisteredScope(String scopeName) {
    Assert.notNull(scopeName, "Scope identifier must not be null");
    return this.scopes.get(scopeName);
}

setSecurityContextProvider

getAccessControlContext

// Set SecurityContextProvider
public void setSecurityContextProvider(SecurityContextProvider securityProvider) {
    this.securityContextProvider = securityProvider;
}
// Get security scope
public AccessControlContext getAccessControlContext() {
    return (this.securityContextProvider != null ?
            this.securityContextProvider.getAccessControlContext() :
            AccessController.getContext());
}

copyConfigurationFrom

Configure replication. Replication includes all standard configuration settings as well as bean post processor, scope, and factory specific internal settings. You should not include any metadata for the actual bean definition, such as the BeanDefinition object and the bean name alias.

public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
    Assert.notNull(otherFactory, "BeanFactory must not be null");
    setBeanClassLoader(otherFactory.getBeanClassLoader());
    setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
    setBeanExpressionResolver(otherFactory.getBeanExpressionResolver());
    setConversionService(otherFactory.getConversionService());
    if (otherFactory instanceof AbstractBeanFactory) {
        AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory;
        this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
        this.customEditors.putAll(otherAbstractFactory.customEditors);
        this.typeConverter = otherAbstractFactory.typeConverter;
        this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
        this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
                otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
        this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
                otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
        this.scopes.putAll(otherAbstractFactory.scopes);
        this.securityContextProvider = otherAbstractFactory.securityContextProvider;
    }
    else {
        setTypeConverter(otherFactory.getTypeConverter());
        String[] otherScopeNames = otherFactory.getRegisteredScopeNames();
        for (String scopeName : otherScopeNames) {
            this.scopes.put(scopeName, otherFactory.getRegisteredScope(scopeName));
        }
    }
}

getMergedBeanDefinition

Merge bean definitions, including those inherited from the parent class

public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
    String beanName = transformedBeanName(name);
    // Efficiently check whether bean definition exists in this factory.
    // If the current container does not have one and the parent class is of ConfigurableBeanFactory type, go to the parent class to find
    if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
        return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
    }
    // Resolve merged bean definition locally.
    // Go and look for it locally.
    return getMergedLocalBeanDefinition(beanName);
}

isFactoryBean

FactoryBean type or not

public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
    // Get beanName
    String beanName = transformedBeanName(name);
    // Get examples
    Object beanInstance = getSingleton(beanName, false);
    // Instantiated direct judgment
    if (beanInstance != null) {
        return (beanInstance instanceof FactoryBean);
    }
    // No singleton instance found -> check bean definition.
    // If there is no instance, and the parent class is ConfigurableBeanFactory, search from the parent class
    if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
        // No bean definition found in this factory -> delegate to parent.
        return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
    }
    return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}

isActuallyInCreation

Is the bean being created, including single and multiple

public boolean isActuallyInCreation(String beanName) {
    return (isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName));
}

isPrototypeCurrentlyInCreation

protected boolean isPrototypeCurrentlyInCreation(String beanName) {
    // The current thread has a value, indicating that multiple instances are being created
    Object curVal = this.prototypesCurrentlyInCreation.get();
    // If it is equal, or in set, it indicates that the created multiple instances include the specified bean
    return (curVal != null &&
            (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}

beforePrototypeCreation

Before creating multiple instances, add the beanName to the prototype currentlycreation. If it is a string, it means that one has been added and converted to set

protected void beforePrototypeCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    if (curVal == null) {
        this.prototypesCurrentlyInCreation.set(beanName);
    }
    else if (curVal instanceof String) {
        Set<String> beanNameSet = new HashSet<>(2);
        beanNameSet.add((String) curVal);
        beanNameSet.add(beanName);
        this.prototypesCurrentlyInCreation.set(beanNameSet);
    }
    else {
        Set<String> beanNameSet = (Set<String>) curVal;
        beanNameSet.add(beanName);
    }
}

afterPrototypeCreation

After multiple instances are created, remove them from prototype currentlycreation

protected void afterPrototypeCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    if (curVal instanceof String) {
        this.prototypesCurrentlyInCreation.remove();
    }
    else if (curVal instanceof Set) {
        Set<String> beanNameSet = (Set<String>) curVal;
        beanNameSet.remove(beanName);
        if (beanNameSet.isEmpty()) {
            this.prototypesCurrentlyInCreation.remove();
        }
    }
}

destroyBean

Destroy bean

public void destroyBean(String beanName, Object beanInstance) {
    destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName));
}
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
}
public void destroyScopedBean(String beanName) {
    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    // Single case and multiple cases cannot be destroyed
    if (mbd.isSingleton() || mbd.isPrototype()) {
        throw new IllegalArgumentException(
                "Bean name '" + beanName + "' does not correspond to an object in a mutable scope");
    }
    String scopeName = mbd.getScope();
    // Cannot delete without corresponding scope
    Scope scope = this.scopes.get(scopeName);
    if (scope == null) {
        throw new IllegalStateException("No Scope SPI registered for scope name '" + scopeName + "'");
    }
    // If initialized, the destroyed method is called
    Object bean = scope.remove(beanName);
    if (bean != null) {
        destroyBean(beanName, bean, mbd);
    }
}

transformedBeanName

There are three ways to get the beanName: one is the original beanName, the other is the plus & and the other is the alias

protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

originalBeanName

Get the original beanName, if any &, add&

protected String originalBeanName(String name) {
    String beanName = transformedBeanName(name);
    if (name.startsWith(FACTORY_BEAN_PREFIX)) {
        beanName = FACTORY_BEAN_PREFIX + beanName;
    }
    return beanName;
}

initBeanWrapper

Initialize BeanWrapper

protected void initBeanWrapper(BeanWrapper bw) {
    bw.setConversionService(getConversionService());
    registerCustomEditors(bw);
}

registerCustomEditors

Batch registration

protected void registerCustomEditors(PropertyEditorRegistry registry) {
    PropertyEditorRegistrySupport registrySupport =
            (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
    if (registrySupport != null) {
        registrySupport.useConfigValueEditors();
    }
    if (!this.propertyEditorRegistrars.isEmpty()) {
        for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
            try {
                // Batch register to propertyeditorregistratirs
                registrar.registerCustomEditors(registry);
            }
            catch (BeanCreationException ex) {
                Throwable rootCause = ex.getMostSpecificCause();
                if (rootCause instanceof BeanCurrentlyInCreationException) {
                    BeanCreationException bce = (BeanCreationException) rootCause;
                    String bceBeanName = bce.getBeanName();
                    if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
                                    "] failed because it tried to obtain currently created bean '" +
                                    ex.getBeanName() + "': " + ex.getMessage());
                        }
                        onSuppressedException(ex);
                        continue;
                    }
                }
                throw ex;
            }
        }
    }
    if (!this.customEditors.isEmpty()) {
        // Batch register customEditors
        this.customEditors.forEach((requiredType, editorClass) ->
                registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
    }
}

getMergedLocalBeanDefinition

getMergedBeanDefinition

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    // Quick check on the concurrent map first, with minimal locking.
    RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
    // It's already there. Go straight back
    if (mbd != null) {
        return mbd;
    }
    return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
        throws BeanDefinitionStoreException {

    return getMergedBeanDefinition(beanName, bd, null);
}
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) {
            // There is no parent class, which is directly created or cloned according to bd type
            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)) {
                        // Merge definition of parent class
                        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.
            // Default single case
            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)
            // Definition of cache bean
            if (containingBd == null && isCacheBeanMetadata()) {
                this.mergedBeanDefinitions.put(beanName, mbd);
            }
        }

        return mbd;
    }
}

checkMergedBeanDefinition

If it's abstract, throw exceptions.

protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
        throws BeanDefinitionStoreException {

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

clearMergedBeanDefinition

Remove bean definition

protected void clearMergedBeanDefinition(String beanName) {
    this.mergedBeanDefinitions.remove(beanName);
}

clearMetadataCache

Remove the bean definition corresponding to the bean that has not been created

public void clearMetadataCache() {
    this.mergedBeanDefinitions.keySet().removeIf(bean -> !isBeanEligibleForMetadataCaching(bean));
}

resolveBeanClass

doResolveBeanClass

protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
        throws CannotLoadBeanClassException {

    try {
        // It has been parsed and returned directly
        if (mbd.hasBeanClass()) {
            return mbd.getBeanClass();
        }
        if (System.getSecurityManager() != null) {
            return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
                doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
        }
        else {
            return doResolveBeanClass(mbd, typesToMatch);
        }
    }
    catch (PrivilegedActionException pae) {
        ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
    }
    catch (ClassNotFoundException ex) {
        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
    }
    catch (LinkageError err) {
        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
    }
}

private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
        throws ClassNotFoundException {

    ClassLoader beanClassLoader = getBeanClassLoader();
    ClassLoader dynamicLoader = beanClassLoader;
    boolean freshResolve = false;

    if (!ObjectUtils.isEmpty(typesToMatch)) {
        // When just doing type checks (i.e. not creating an actual instance yet),
        // use the specified temporary class loader (e.g. in a weaving scenario).
        ClassLoader tempClassLoader = getTempClassLoader();
        if (tempClassLoader != null) {
            dynamicLoader = tempClassLoader;
            freshResolve = true;
            if (tempClassLoader instanceof DecoratingClassLoader) {
                DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
                for (Class<?> typeToMatch : typesToMatch) {
                    // Temporary loaders exclude these types
                    dcl.excludeClass(typeToMatch.getName());
                }
            }
        }
    }

    String className = mbd.getBeanClassName();
    if (className != null) {
        // Expression parser parsing of bean
        Object evaluated = evaluateBeanDefinitionString(className, mbd);
        // Different class names
        if (!className.equals(evaluated)) {
            // A dynamically resolved expression, supported as of 4.2...
            // It's a direct return of class type
            if (evaluated instanceof Class) {
                return (Class<?>) evaluated;
            }
            // The string freshResolve is true
            else if (evaluated instanceof String) {
                className = (String) evaluated;
                freshResolve = true;
            }
            else {
                throw new IllegalStateException("Invalid class name expression result: " + evaluated);
            }
        }
        if (freshResolve) {
            // When resolving against a temporary class loader, exit early in order
            // to avoid storing the resolved Class in the bean definition.
            //The class name is the same, and it is a string
            if (dynamicLoader != null) {
                try {
                    // Class loader loading
                    return dynamicLoader.loadClass(className);
                }
                catch (ClassNotFoundException ex) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
                    }
                }
            }
            // No classloader
            return ClassUtils.forName(className, dynamicLoader);
        }
    }

    // Resolve regularly, caching the result in the BeanDefinition...
    // Parsing and buffering in bean definition
    return mbd.resolveBeanClass(beanClassLoader);
}

evaluateBeanDefinitionString

protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) {
    // The expression resolver of bean is empty and returns value directly
    if (this.beanExpressionResolver == null) {
        return value;
    }
    // It's not empty. Take scope to parse
    Scope scope = null;
    if (beanDefinition != null) {
        String scopeName = beanDefinition.getScope();
        if (scopeName != null) {
            scope = getRegisteredScope(scopeName);
        }
    }
    return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}

predictBeanType

Type of prediction bean

protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
    // If targetType is not empty, return directly
    Class<?> targetType = mbd.getTargetType();
    if (targetType != null) {
        return targetType;
    }
    if (mbd.getFactoryMethodName() != null) {
        return null;
    }
    return resolveBeanClass(mbd, beanName, typesToMatch);
}

isFactoryBean

protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
    // Get resolved type
    Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
    // Returns true if the resolved type is not empty and FactoryBean
    return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
}

getTypeForFactoryBean

//Get the type of FactoryBean through beanName and definition

protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
    if (!mbd.isSingleton()) {
        return null;
    }
    try {
        FactoryBean<?> factoryBean = doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);
        return getTypeForFactoryBean(factoryBean);
    }
    catch (BeanCreationException ex) {
        if (ex.contains(BeanCurrentlyInCreationException.class)) {
            if (logger.isTraceEnabled()) {
                logger.trace("Bean currently in creation on FactoryBean type check: " + ex);
            }
        }
        else if (mbd.isLazyInit()) {
            if (logger.isTraceEnabled()) {
                logger.trace("Bean creation exception on lazy FactoryBean type check: " + ex);
            }
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean creation exception on non-lazy FactoryBean type check: " + ex);
            }
        }
        onSuppressedException(ex);
        return null;
    }
}

markBeanAsCreated

If not added to alreadyCreated, clear the definition of the current bean and add it to alreadyCreated

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);
            }
        }
    }
}

cleanupAfterBeanCreationFailure

Remove from alreadyCreated after creation failure

protected void cleanupAfterBeanCreationFailure(String beanName) {
    synchronized (this.mergedBeanDefinitions) {
        this.alreadyCreated.remove(beanName);
    }
}

isBeanEligibleForMetadataCaching

Created or not

protected boolean isBeanEligibleForMetadataCaching(String beanName) {
    return this.alreadyCreated.contains(beanName);
}

removeSingletonIfCreatedForTypeCheckOnly

Remove singleton not in alreadyCreated

protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
    if (!this.alreadyCreated.contains(beanName)) {
        removeSingleton(beanName);
        return true;
    }
    else {
        return false;
    }
}

hasBeanCreationStarted

Whether a bean has been created. alreadyCreated is empty, indicating that it has not been created. It is not empty. It has been created

protected boolean hasBeanCreationStarted() {
    return !this.alreadyCreated.isEmpty();
}

getObjectForBeanInstance

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.
    // If the beanname starts with & the bean must be of type FactoryBean
    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.
    // Normal bean or beanname starts with & and returns beanInstance
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    // It's FactoryBean, but it doesn't start with
    Object object = null;
    if (mbd == null) {
        // The definition information of the bean is empty. Take it from the cache
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        //Cache does not exist
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        // The mdb is empty and has been instantiated
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);//Return the getObject method of factory
    }
    return object;
}

isBeanNameInUse

Judging whether the bean name has been used from aliases, bean definitions and dependencies

public boolean isBeanNameInUse(String beanName) {
    return isAlias(beanName) || containsLocalBean(beanName) || hasDependentBean(beanName);
}

requiresDestruction

Determines whether a given bean needs to be destroyed on shutdown

protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
    return (bean.getClass() != NullBean.class &&
            (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
                    DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}

registerDisposableBeanIfNecessary

Register a one-time bean, only for a single instance

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    // Not many and need to be destroyed
    if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
        if (mbd.isSingleton()) {
            // Register a DisposableBean implementation that performs all destruction
            // work for the given bean: DestructionAwareBeanPostProcessors,
            // DisposableBean interface, custom destroy method.
            registerDisposableBean(beanName,
                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
        }
        else {
            // A bean with a custom scope...
            Scope scope = this.scopes.get(mbd.getScope());
            if (scope == null) {
                throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
            }
            scope.registerDestructionCallback(beanName,
                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
        }
    }
}

containsBeanDefinition

Whether the bean definition of the specified bean already exists

getBeanDefinition

Get the bean definition according to the specified bean

createBean

Create bean

Posted by WeddingLink on Mon, 04 Nov 2019 23:18:39 -0800