After analyzing the Spring IOC container’s dependency injection and bean instantiation, let’s take a look at the doCreateBean method
Continue the analysis of the previous bean instantiation process and the implementation of dependency injection in it
- AbstractBeanFactory
- DoGetBean Gets the bean instance
- DefaultSingletonRegistry
- GetSingleton Gets the singleton instance
- Level 3 caching resolves circular dependencies
- AbstractAutowireCapableBeanFactory
- CreateBean Preparation for creating a bean instance
- DoCreateBean Creates a bean instance
- ApplyMergedBeanDefinitionPostProcessors @ Autowriet and @ the Value
- PopulateBean injects property values into the bean instance (dependency injection)
- AutowiredAnnotationBeanPostProcessor
- PostProcessProperties Autowriet dependency injection logic
- DefaultListableBeanFactory
- DoResolveDependency Dependency resolution
- DependencyDescriptor
- Extends InjectionPoint Extends InjectionPoint dependency injection instance
Analysis of the
We now look at the source code for creating bean instances. From the previous article we know that doCreateBean does roughly five things:
- CreateBeanInstance: createBeanInstance
- Call the BeanDefinition attribute after the BeanPostProcessor has been merged
- Populate the bean instance property: populateBean
- Call the bean’s initialization method: initializeBean
- Registered bean is a logic: the destruction of registerDisposableBeanIfNecessary
Finally, return the created bean instance object
CreateBeanInstance: createBeanInstance
Create a new instance of the specified bean with the appropriate instantiation policy: factory method, constructor autowire, or simple instantiation.
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Try to get the class object in the beanClass<? > beanClass = resolveBeanClass(mbd, beanName);// Check whether you have permission to create private classes using reflection
if(beanClass ! =null&&! Modifier.isPublic(beanClass.getModifiers()) && ! mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// Create an instance using the factory methodSupplier<? > instanceSupplier = mbd.getInstanceSupplier();if(instanceSupplier ! =null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// If the factory method is not empty, then the factory method initialization strategy is used
if(mbd.getFactoryMethodName() ! =null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// If the cached parsed constructor or factory method is not empty, then the constructor can be parsed
// Because you need to determine which constructor to use based on the arguments
if(mbd.resolvedConstructorOrFactoryMethod ! =null) {
resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; }}}if (resolved) {
// Automatic injection, call the constructor to automatically inject
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null.null);
}
else {
// Use the default constructor
returninstantiateBean(beanName, mbd); }}// Use the constructor that takes a parameter to assembleConstructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors ! =null|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || ! ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if(ctors ! =null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// Use the default constructor
return instantiateBean(beanName, mbd);
}
Copy the code
We note that if the factory method is not null, use the factory method initialization strategy, in the main is to call ConstructorResolver# instantiateUsingFactoryMethod method to create the bean instance.
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
// Initialize BeanWrapperImpl
// Add the ConversionService object and the PropertyEditor object to the BeanWrapper object
this.beanFactory.initBeanWrapper(bw); Object factoryBean; Class<? > factoryClass;boolean isStatic;
// The factory name is not empty
String factoryBeanName = mbd.getFactoryBeanName();
if(factoryBeanName ! =null) {
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// Get the factory instance
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// If the factory name is null, it may be a static factory
// To create a static factory, you must provide the full class name of the factory
if(! mbd.hasBeanClass()) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
// Factory method
Method factoryMethodToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// Factory method parameters
// If a construct parameter is specified, use it directly
// When calling the getBean method, specify the method parameters
if(explicitArgs ! =null) {
argsToUse = explicitArgs;
}
else {
// If it is not specified, an attempt is made to parse from the configuration file
Object[] argsToResolve = null;
// First try to get it from the cache
synchronized (mbd.constructorArgumentLock) {
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
// Get the constructor or factory method in the cache
if(factoryMethodToUse ! =null && mbd.constructorArgumentsResolved) {
// Get the construct parameters in the cache
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// Get the package-visible fields of the constructor arguments in the cacheargsToResolve = mbd.preparedConstructorArguments; }}}// If BeanDefinition does not exist in the cache, the parameter stored in BeanDefinition is resolved
/ / such as the constructor of A given method (int, int), after by this method will be put in the configuration file (" 1 ", "1") into (1, 1)
// The value in the cache may be the original value or the final value
if(argsToResolve ! =null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true); }}// The getBean method is called with no parameters, and this is the first time the factory method is used
if (factoryMethodToUse == null || argsToUse == null) {
// Get the full class name of the factory method
factoryClass = ClassUtils.getUserClass(factoryClass);
List<Method> candidateList = null;
if (mbd.isFactoryMethodUnique) {
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
// Get all methods that meet the criteria
if(factoryMethodToUse ! =null) { candidateList = Collections.singletonList(factoryMethodToUse); }}if (candidateList == null) {
candidateList = new ArrayList<>();
// Retrieve all methods. In this case, filter the methods
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
for (Method candidate : rawCandidates) {
// If there is a static factory method, add it to candidateSet
if(Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) { candidateList.add(candidate); }}}// When there is only one candidate method with the same name as the factory method and the getBean method is called with no arguments passed,
// Execute the candidate method directly by calling the instantiated method without caching the arguments
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidateList.get(0);
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
Method[] candidates = candidateList.toArray(new Method[0]);
// Sort constructor
// The number of public constructor arguments is in descending order, and the number of non-public constructor arguments is in descending order
AutowireUtils.sortFactoryMethods(candidates);
// When there are multiple candidate methods with the same name as the factory method, sort them. Public methods are sorted first, then methods with more arguments are sorted first
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;
int minNrOfArgs;
// If the getBean method is called with parameters, then the factory method must have a minimum number of parameters equal to the number of parameters passed
if(explicitArgs ! =null) {
minNrOfArgs = explicitArgs.length;
}
else {
// getBean() passes no arguments, so the arguments stored in the BeanDefinition constructor need to be parsed
if (mbd.hasConstructorArgumentValues()) {
// Constructor parameters
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// Parse the constructor parameters
// Resolve the constructor arguments of the bean to an object called resolvedValues, where other beans are involved
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}
LinkedList<UnsatisfiedDependencyException> causes = null;
// Iterates over candidate methods with the same name
for (Method candidate : candidates) {
// Get the parameter list of the candidate methodClass<? >[] paramTypes = candidate.getParameterTypes();if (paramTypes.length >= minNrOfArgs) {
ArgumentsHolder argsHolder;
// When the getBean method is called, the parameter number of the factory method must be the same as
// Pass the exact same number of parameters
if(explicitArgs ! =null) {
// Displays the given parameters, which must match exactly in length
if(paramTypes.length ! = explicitArgs.length) {continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
try {
String[] paramNames = null;
// Get the ParameterNameDiscoverer object
// ParameterNameDiscoverer is an interface for parsing the parameter names of methods and constructors
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if(pnd ! =null) {
paramNames = pnd.getParameterNames(candidate);
}
// When the passed parameter is null, we need to inject the corresponding bean according to the parameter type of the factory method
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
}
catch(UnsatisfiedDependencyException ex) {...continue; }}/ / isLenientConstructorResolution whether when parsing constructor in easing mode or strict mode
// Strict mode: when parsing a constructor, all must match, otherwise an exception is thrown
// Loose mode: matches using the "closest mode"
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// represents the closest type match, then select as the constructor
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// Collect this type option if methods with the same number of parameters have the same type difference weight
// However, this check is performed only in non-loose constructor parsing mode, and override methods (which have the same parameter signatures) are explicitly ignored.
else if(factoryMethodToUse ! =null&& typeDiffWeight == minTypeDiffWeight && ! mbd.isLenientConstructorResolution() && paramTypes.length == factoryMethodToUse.getParameterCount() && ! Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {// Find multiple matching methods
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = newLinkedHashSet<>(); ambiguousFactoryMethods.add(factoryMethodToUse); } ambiguousFactoryMethods.add(candidate); }}}// There is no executable factory method, throw an exception...if (explicitArgs == null&& argsHolderToUse ! =null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
// Add the parsed constructor to the cache
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}
Copy the code
You can see that the methods are quite long, but it’s not hard to understand that they are all preparing for instantiating the bean, and ultimately calling the Instantiate method to create the sample bean by executing the factory method.
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
if(System.getSecurityManager() ! =null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
this.beanFactory.getAccessControlContext());
}
else {
// Create the bean sample by executing the factory method
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args); }}catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via factory method failed", ex); }}Copy the code
Good, we go back and look at AbstractAutowireCapableBeanFactory# createBeanInstance method, found the follow-up is also going to call instantiate method to by executing the factory method to create bean example. It turns out that all of them are getting instances by reflection.
Call the BeanDefinition attribute after the BeanPostProcessor has been merged
After looking at the createBeanInstance method, let’s continue to look inside the doCreateBean method
synchronized (mbd.postProcessingLock) {
if(! mbd.postProcessed) {try {
// Properties marked by @autowired and @value are fetched here
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
// Exception handling......
mbd.postProcessed = true; }}Copy the code
You can see mainly perform applyMergedBeanDefinitionPostProcessors method, This method is mainly carried out MergedBeanDefinitionPostProcessor# postProcessMergedBeanDefinition break points in the method, Found that the interface is a subclass AutowiredAnnotationBeanPostProcessor to implementation, the AutowiredAnnotationBeanPostProcessor created as follows:
public AutowiredAnnotationBeanPostProcessor(a) {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
} catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.}}Copy the code
Autowired, Value, and Inject tags will be added, so the main step in this step is to get the attributes of @autowired and @value tags here
Populate the bean instance property: populateBean
Let’s follow up the doCreateBean method and populate the properties for the created bean instance
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {.../ / to InstantiationAwareBeanPostProcessors last chance before the property into modified Bean attribute value, can also control whether to fill the Bean
/ / by calling the specific postProcessAfterInstantiation method, if the call returns false, said don't need to continue the dependency injection, returned directly
// Attribute injection can be customized by the user. Implement a InstantiationAwareBeanPostProcessor types such as user's post processor,
/ / and through postProcessAfterInstantiation method to the bean's member variables into the custom information.
boolean continueWithPropertyPopulation = true;
if(! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if(! ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation =false;
break; }}}}/ / if the above Settings continueWithPropertyPopulation = false, indicating that the user may have their fill
// The properties of the bean do not need to be filled by Spring. You can just go back
if(! continueWithPropertyPopulation) {return;
}
// PVS is a MutablePropertyValues instance that implements the PropertyValues interface,
// Provides read/write operations on properties, and deep copy can be implemented by calling constructors
BeanDefinition = BeanDefinition = BeanDefinition = BeanDefinition
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// The default is 0, which means that all dependency injection needs to be explicitly configured in the XML file
// If the related dependency assembly mode is set, the properties of the Bean will be traversed to complete the corresponding injection by type or name, no additional configuration is required
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Set autowiring based on beanName
// ps:
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Autowiring is processed automatically based on the type of the Bean
// ps:
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
Whether registered InstantiationAwareBeanPostProcessor / / container
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// Whether to check dependencies. Default is false
booleanneedsDepCheck = (mbd.getDependencyCheck() ! = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds =null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// This is where dependency injection is performed on the @autowired tag properties
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// Parsed properties that are not set are processed again
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return; } } pvs = pvsToUse; }}}// This attribute is deprecated in 3.0
if (needsDepCheck) {
// Filter out all attribute editors that need dependency checking
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if(pvs ! =null) {
// Finally, the property is injected into the Bean Wrapper instance. The injection is for properties explicitly configured with autowiredbyName or ByType.
/ / for comments, because the AutowiredAnnotationBeanPostProcessor have already completed the injection,
// So it is not executed hereapplyPropertyValues(beanName, mbd, bw, pvs); }}Copy the code
As you can see, this method mainly gets the BeanDefinition to set the related property values for the Bean, and does the dependency injection for the properties of the @AutoWired tag by name or type. The bean’s initialization method is then called.
Call the bean’s initialization method: initializeBean
Let’s go straight into the method view:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if(System.getSecurityManager() ! =null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null| |! mbd.isSynthetic()) {// The pre-initialization of the bean
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw newBeanCreationException( (mbd ! =null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null| |! mbd.isSynthetic()) {// Post operation of bean initialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
Copy the code
The following steps are taken to discover the initialization of the bean:
- Determine if BeanNameAware, BeanClassLoaderAware, and BeanFactoryAware methods are implemented, and set the relevant properties if they are.
- Calls the BeanPostProcessor operation initialized by the bean.
- Perform the initialization method. AfterPropertiesSet is called if initializingBean is present, and the initial method is called if InitMethod is present.
- Calls the BeanPostProcessor operation initialized by the bean.
Registered bean is a logic: the destruction of registerDisposableBeanIfNecessary
Finally, let’s look at the last method in doCreateBean to register the bean’s destruction logic:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { AccessControlContext acc = (System.getSecurityManager() ! =null ? getAccessControlContext() : null);
// Not prototype and the bean needs to be destroyed
if(! mbd.isPrototype() && requiresDestruction(bean, mbd)) {if (mbd.isSingleton()) {
// The bean that needs to be destroyed in singleton mode
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// Customize the processing of 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,
newDisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); }}}Copy the code
Let’s take a look at the judgment of requiresDestruction:
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return(bean.getClass() ! = NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors())))); }Copy the code
Take a look at each of these two methods in DisposableBeanAdapter:
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
// If the DisposableBean interface or AutoCloseable interface is implemented, there is a disposal method
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
// Get the destoryMethodName property from beanDefinition
String destroyMethodName = beanDefinition.getDestroyMethodName();
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName)) {
// What does the class say if it has a close or shutdown method? // What does the class say if it has a close or shutdown method
return (ClassUtils.hasMethod(bean.getClass(), CLOSE_METHOD_NAME) ||
ClassUtils.hasMethod(bean.getClass(), SHUTDOWN_METHOD_NAME));
}
// See if there is any configuration
return StringUtils.hasLength(destroyMethodName);
}
/ / if there is a registered DestructionAwareBeanPostProcessor container, you will also have the following this method's judgment
public static boolean hasApplicableProcessors(Object bean, List<BeanPostProcessor> postProcessors) {
if(! CollectionUtils.isEmpty(postProcessors)) {for (BeanPostProcessor processor : postProcessors) {
if (processor instanceof DestructionAwareBeanPostProcessor) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
// The destruction method is not empty
if (dabpp.requiresDestruction(bean)) {
return true; }}}}return false;
}
Copy the code
Sure is a need to destroy the singleton beans, spring will wrap it as a a DisposableBean and registered to DefaultSingletonBeanRegistry:
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
// Put to disposableBeans Map
this.disposableBeans.put(beanName, bean); }}Copy the code
summary
Ok, in this article we mainly learned about the doCreateBean method. In simple terms, this method mainly creates a bean that can be used directly and returns it to the calling layer for use.