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