General documentation: Article directory Github: github.com/black-ant
A. The preface
The Spring IOC system is a structure that is well worth studying and studying. Only by reading it can you have a better understanding.
This article focuses on a large process transformation in the entire CreateBean process to help you find the cause of the problem:
The purpose of this article:
- Comb through the creation process of beans to facilitate subsequent problem finding
- The parameters in the process are combed to reduce the need for debugging
- Comb the whole family system
Bean creates several trigger scenarios:
- The BeanFactory # getBean (…). Method to request an instance object
- When using the ApplicationContext container, some beans are registered immediately at startup
2. Process sorting
Let’s start with a very common picture, from @Topjava. Cn/article / 139…
Similarly, the process of this article is also according to this process, first look at the entire process outline
> Instantiate procedure1Instantiate Bean objects: Does the Spring container instantiate beans according to the instantiation policy? - strategy pattern is commonly used, usually include reflection and additional dynamic bytecode - SimpleInstantiationStrategy: reflection - CglibSubclassingInstantiationStrategy: Dynamic bytecode via CGLIB (default) - createBeanInstance(...) BeanWrapper: the core interface to the low-level Bean infrastructure? - Low-level beans: Without any properties - BeanWrapperImpl to "package" of Bean, used in injection Bean properties | - InstantiationStrategy - > SimpleInstantiationStrategy | - SimpleInstantiationStrategy -> CglibSubclassingInstantiationStrategy2Injection object properties | - instantiation is completed, if the bean set up some of the properties, use the set method to set some attributes3Detection, Activate the Aware | - perception BeanNameAware, BeanClassLoaderAware, BeanFactoryAware | | - if the Bean implements BeanNameAware interface - the call # setBeanName (String beanName) method4BeanPostProcessor pre-processing | | - if the bean implements BeanClassLoaderAware interface - call the setBeanClassLoader (this this) method. | | - if the bean implements BeanFactoryAware interface - call the setBeanFactory (the BeanFactory the BeanFactory) methods | - if the vessel is registered BeanPostProcessor | - Will call # postProcessBeforeInitialization | - finishing bean processing5Check the InitializingBean and init method - | - if the bean implements InitializingBean interface | - call the # afterPropertiesSet () method | - if the bean configuration Init-method method, the method specified by it is called.6Rear BeanPostProcessor processing | - initialization complete, if the vessel is registered BeanPostProcessor | - will call # postProcessAfterInitialization, complete rear bean processing.7Register the necessary Destruction callbacks8Using Bean | - initialized object is complete, start method call9Check the DisposableBean and destory - method | - before its closure in the container, if the bean implements DisposableBean interfaces # | - call the destroy () method before | - in closed container, If the bean is configured with a destroy - method | - invoke the specified method.Copy the code
2.1 Instantiate creation
Introduction: Who called it?
There are two ways to call doGetBean:
One is that when the ApplicationContext is loaded, it initializes the beans needed by the current container: C- SpringApplication # run C- SpringApplication # prepareContext C- SpringApplication # applyInitializers : Call ApplicationContextInitializer collection, Execute the corresponding respectively the initialize C – ApplicationContextInitializer # # the initialize C – ConditionEvaluationReport get C – AbstractBeanFactory # getBean
The second is for the container to process all the necessary beans at Refresh after they have been loaded
- C- SpringApplication # run
- C- SpringApplication # refreshContext
- C- AbstractApplicationContext # refresh()
- There are several places in Refresh where getBean is called
- C- AbstractApplicationContext # invokeBeanFactoryPostProcessors
- C- AbstractApplicationContext # registerBeanPostProcessors
- C- AbstractApplicationContext # onRefresh();
- C- AbstractApplicationContext # finishBeanFactoryInitialization
- C- AbstractBeanFactory # getBean
PS: Another is called recursively because of dependencies
2.1.1 doGetBean entrance
C171- AbstractBeanFactory M171_01- getBean(String name, Class<T> requiredType) ? - Call doGetBean directly, which will call different getBeans depending on the typeCopy the code
DoGetBean can be divided into five phases
- Phase 1: Generate a beanName and try to get it from the singleton cache
- Phase 2: After the singleton cache fails to obtain the file, try to obtain the file from ParentBeanFactory
- Phase 3: Dependency checking to ensure that the beans on which the current bean depends are initialized
- Phase 4: Getting Bean instances with three different types (Singleton/prototype/other)
- Phase 5: At this point the Bean is ready, and the required type is checked to see if it matches the type of the actual Bean instance
// Core method 1:
M171_02- doGetBean( String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly)
// Phase 1: Generate a beanName and try to get it from the singleton cache
1- transformedBeanName Generates a beanName -> PS:M171_02_012-> -> PS:M171_02_02 if-sharedInstance! -> -> PS:M171_02_02 if-sharedInstance! =null-getobjectForBeanInstance (sharedInstance, name, beanName, name)null)
// Phase 2: After the singleton cache fails to obtain the value, try to obtain the value from ParentBeanFactory
ELSE-
3- isPrototypeCurrentlyInCreation (beanName) : if there is a prototype model and circular dependencies, throw an exception4-getParentBeanFactory () : Check whether there are bean definitions in this factory? - If the factory already exists, there are four situations that will be directreturn -> PS:M171_02_03
4.1- AbstractBeanFactory : parentBeanFactory.doGetBean
4.2- args ! =null : parentBeanFactory.getBean(nameToLookup, args)
4.3- requiredType ! =null: parentBeanFactory.getBean(nameToLookup, requiredType)
4.4- Do not match: ParentBeanFactory. GetBean (nameToLookup) - if for instance for the type check, Rather than actually using it, Will be marked the specified bean has been created - > PS: M171_02_04 - RootBeanDefinition MBD = getMergedLocalBeanDefinition (beanName) + checkMergedBeanDefinition ? - RootBeanDefinition obtains and checks LV171_001// Phase 3: dependency check to ensure that the current bean depends on the initialized bean- FOR LV171_001: MBD, get all dependencies via getDependsOn - loop all dependencies recursively by calling registerDependentBean + getBean respectivelyPhase 4: Three different types get Bean instances
5- Create a Bean based on the different Bean types -> PS:M171_02_055.1- isSingleton : getSingleton + createBean + getObjectForBeanInstance
5.2- isPrototype : beforePrototypeCreation + createBean + afterPrototypeCreation + getObjectForBeanInstance
5.3- Others: Mainly control the domain + Prototype process through Scope// Stage 5: The Bean is now ready. This is where you check to see if the required type matches the type of the actual Bean instanceIF- IF the instances do not match, the conversion is required, and the conversion directly returns -return getTypeConverter().convertIfNecessary(bean, requiredType)
// If not, return the original Bean
// Other methodsM171_10- getSingleton(String beanName, ObjectFactory<? M171_20- getObject() : is this actually a call to FactoryBean? - This will call createBean via a method callback syntax sugar, and the whole thing will be connected -> M173_02// Core method 2: instantiate beans
// The first thing to know is what is passed: TODO
M171_ - getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)
// PS: doGetBean is shown in the appendix
Copy the code
2.1.2 doGetBean Adds a node
PS: get beanName M171_02_01
--> canonicalName(BeanFactoryUtils.transformedBeanName(name)) ----> C181- SimpleAliasRegistry F181_01- Map<String, String > aliasMap M - canonicalName (BeanFactoryUtils transformedBeanName (name)) - mainly from obtaining the alias F181_01 alias? -ps: The code here is interesting, it seems to be to solve the alias chain problem, that is, the alias corresponding to the alias, until you can not get outpublic String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if(resolvedName ! =null) {
canonicalName = resolvedName;
}
// Loop to obtain whether the alias corresponding to the alias exists until the alias cannot be obtained
}while(resolvedName ! =null);
return canonicalName;
}
Copy the code
PS:M171_02_03 Why do four cases return directly?
4.1- AbstractBeanFactory : parentBeanFactory.doGetBean
4.2- args ! =null: parentBeanFactory.getBean(nameToLookup, args) ? - Delegate to the parent class with explicit arguments4.3- requiredType ! =null: parentBeanFactory.getBean(nameToLookup, requiredType) ? - Delegate to the standard getBean method4.4- do not conform to: parentBeanFactory getBean (nameToLookup)? - Pro2/ / here returned directly because there is a parent the BeanFactory, BeanDefinition and existence, which means ParentBeanFactory can handle, based on the reason of Pro 1, choose returned directly
-> BeanFactory parentBeanFactory = getParentBeanFactory();This is a recursive operation, and it is handled in the same way as the parent delegate, that is, the parent object first loads the corresponding object. Likewise, when doGet is entered, the default is to load the Bean through the parent method. If the parent method is completed, that is, the Bean is loaded, and the benefit is returned directly. With a little thought, you can ensure that each implementation can focus on the beans it needs to handle, and not on the beans that would have been loaded in the first place. Recall the purpose of parent delegation: avoid reloading + avoid core class tampering// Pro 2: Four ways to return the difference
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
Copy the code
PS: What purpose does M171_02_04 serve for the process-only check?
Here, if you just check without creating, you do it in the markBeanAsCreated method2Thing clearMergedBeanDefinition (beanName);this.alreadyCreated.add(beanName); The goal is to avoid unnecessary iterations of the process, allowing the bean factory to optimize its cache for repeated creation of specified beans, even though the annotation method has been checked successfully// Step 1: What is alreadyCreated?
Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); ? - alreadyCreated A Set containing the names of beans that have been created at least once// Step 2: How to use this object?
1: AbstractAutowireCapableBeanFactory # getTypeForFactoryBean ? - this will verify that the referenced FactoryBean does not yet exist through this object, so exit here -- it will not force the creation of another bean just to get the object type of FactoryBean2: When clearMetadata is used, check whether it is emptyCopy the code
PS:M171_02_05 Three different ways of the essential difference?
Similarity: The final call to getObjectForBeanInstance5.1- isSingleton : GetSingleton + createBean + getObjectForBeanInstance - getSingleton + createBean + getObjectForBeanInstance Ensure unique loading - the createBean callback creates the Bean - and instantiate the real Bean via getObjectForBeanInstance5.2- isPrototype : BeforePrototypeCreation + createBean + afterPrototypeCreation + getObjectForBeanInstance - If you look closely, there is no scope object control Create it directly5.3- other: Control domain via Scope + Prototype process - it is a combination of Singleton, - first prepare a Scope object to control the Bean situation within Scope - then call the same process as Prototype to createCopy the code
M171_02_06 sharedInstance and bean
You can see the difference between creating an Object sharedInstance with createBean and generating a Bean with getObjectForBeanInstance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}catch (BeansException ex) {
destroySingleton(beanName);
throwex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }// This is where the Bean factory comes in. Normally, createBean creates a full Bean
However, if it is a FactoryBean, you need to use it to create an instance of the bean, unless the caller actually wants a reference to the factory.
Copy the code
The beans in sharedInstance are the beans that have already gone through the Bean creation process
2.1.3 AbstractBeanFactory # createBean
C171- AbstractBeanFactory M171_03- createBean(String beanName, RootBeanDefinition mbd, Object[] args) P- mbd : BeanDefinition object, which has merged the parent class property p-args: the parameter used by the constructor or factory method to create the Bean instance objectCopy the code
2.1.4 AbstractAutowireCapableBeanFactory # createBean main process
C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory M173_02- createBean(String beanName, RootBeanDefinition mbd,Object[] args) ? - default implementation of the M170_01 method LV173_02_01- RootBeanDefinition mbdToUse: an internal attribute that identifies the RootBeanDefinition1- Class<? > resolvedClass = resolveBeanClass(mbd, beanName) -> PS:M173_02_01 ? - Parse to obtain the specified BeanDefinitionclassProperties - >M173_04
IF- resolvedClassDon't fornullAnd there areBeanClass 和 BeanClassName
- new RootBeanDefinition(mbd)
- mbdToUse.setBeanClass(resolvedClass) 2 -mbdToUse.prepareMethodOverrides() : processingOverridesProperties - >PS:M173_02_02
- GetMethodOverrides().getOverrides()
- prepareMethodOverride(MethodOverride mo) 3 -Object bean = resolveBeforeInstantiation (beanName, mbdToUse) instantiated preposition - if the beannull(Directly returned because the previous step generated a proxy class,AOP)4- Object beanInstance = doCreateBean(beanName, mbdToUse, args); M173_03 -createBean (String beanName, RootBeanDefinition MBD,@NullableObject[] args) m173_04-resolveBeanClass: resolves the bean class name toclassReference / /PS:M173_02_01 RootBeanDefinition/ / make surebeanThe class is actually resolved at this point, if dynamically resolvedclassCannot be stored in a shared mergebeanDefinition, clonebeandefineRootBeanDefinition mbdToUse = mbd; Class<? > resolvedClass = resolveBeanClass(mbd, beanName);if(resolvedClass ! =null&&! mbd.hasBeanClass() && mbd.getBeanClassName() ! =null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// PS:M173_02_02 prepareMethodOverrides Processes Overrides
public void prepareMethodOverrides(a) throws BeanDefinitionValidationException {
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride); }}>>>>>>> corresponds to the prepareMethodOverride method
C- AbstractBeanDefinition
M- prepareMethodOverride(MethodOverride mo)
1- ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()) ? - Obtains the number of methods corresponding to the current Method Name2- if there is no corresponding method, throw BeanDefinitionValidationException3- 如果 count = 1, marks the Overloaded as unoverloaded, and on subsequent calls, you can find the method 'Overloaded' directly without checking the method parameters// M173_02 source introduction
M- createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
- beanInstance = this.doCreateBean(beanName, mbdToUse, args); -> M173_05
Copy the code
DoCreateBean main process
DoCreate is divided into several steps:
C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory M173_05- doCreateBean(beanName, mbdToUse, args) : Create Bean objects? - Regular Bean creation for non-proxy objects with the following primary nodes - Prepare BeanWrapper: BeanWrapper is the wrapper around the Bean - if the singleton model is removed from the FactoryBean cache that never completes - createBeanInstance(beanName, MBD, args) : Enter the Bean creation process and create a BeanWrapper for the Bean. - If this is a singleton, then get it directly, and remove the object from the cache? - otherwise call createBeanInstance access - instanceWrapper. GetWrappedInstance (); ? - packing an instance of the object - instanceWrapper. GetWrappedClass (); ? - packing IF an instance of the object type - applyMergedBeanDefinitionPostProcessors? - Post processing, if any, is performed here,synchronizedLock if-addSingletonFactory? M173_30 - initializeBean: initializeBean: initializeBean? PS:M173_05_03 if-getSingleton? PS:M173_05_03 if-getSingleton? - In the case of circular dependencies, the initial dependency bean is recursed, returning an empty object for circular processing. -2Kind of situation, All returned early object or getDependentBeans recursive - > PS: M173_05_01 - registerDisposableBeanIfNecessary M173_07 prepareMethodOverrides - Get all the Overrides, PrepareMethodOverride -> M173_08 M173_08- prepareMethodOverride - getMethodOverrides().getoverrides ().foreach () preparemethodoverrides ().getoverrides ().foreach (this::prepareMethodOverride) ? PrepareMethodOverride M173_10 -autoWirebyName: Complete automatic dependency injection based on property name M173_11 -autoWirebyType: ResolveDependency -> resolveDependency M173_12- resolveDependency M173_12- resolveDependency M173_12- resolveDependency -doresolvedependency M173_13- doResolveDependency M173_15- applyPropertyValues: doResolveDependency M173_13- doResolveDependency M173_15- applyPropertyValues M173_50-initializebean applied to the bean that has been instantiated// doCreateBean core code flow
M- doCreateBean(String beanName, RootBeanDefinition mbd, @NullableObject[] args) : createBean main process -mbD.issingleton () : After the judgment for BeanWrapper (ConfigurationClassPostProcessor) - instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
- instanceWrapper = this.createBeanInstance(beanName, mbd, args);
- this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
- this.populateBean(beanName, MBD, instanceWrapper) : Mainly property population-step1 : bw == null&& mbD.hasPropertyValues () : BeanWrapper null judgment -step2 : thisGetBeanPostProcessors (). The iterator () : iterative BeanPostProcessors - ibp. PostProcessAfterInstantiation: here is After - Step3: Gets the PropertyValue and injects -step through autowireByName or autowireByType4 : hasInstantiationAwareBeanPostProcessors
- this.getBeanPostProcessors().iterator();
- ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
- Step 5 :
- Step 6 : thisCheckDependencies (beanName, MBD, filteredPds, (PropertyValues) PVS) : checkDependencies -step7 : this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs) :
- this.initializeBean(beanName, exposedObject, mbd);
- this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
// Addendum: M173_05 doCreateBean
Copy the code
PS:M173_05_01: recursive loop detail
In doCreateBean, circular dependencies are handled// In the case of a cyclic dependency, the initial dependency bean is recursed, returning an empty object for cyclic processing
// Return an earlier object or getDependentBeans recursively owned
if (earlySingletonExposure) {
// Refer to the chapter on circular dependencies, which may return an incomplete preobject reference
// If there is a cyclic dependency, this is not null
Object earlySingletonReference = getSingleton(beanName, false);
if(earlySingletonReference ! =null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
// Determines that circular dependencies exist
}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
Return the names of all beans (if any) that depend on the specified bean.
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// If it is used for purposes other than type checking, it cannot be deleted -> PS:M173_05_03
if(! removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {// If you do not need to delete it, add itactualDependentBeans.add(dependentBean); }}// Because of the previous addition, a dependency is formed here
if(! actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException("..."); }}}}// PS:M173_05_03: What are the other purposes?Core is checking alreadyCreated removeSingletonIfCreatedForTypeCheckOnly1If alreadyCreated already exists, the object is alreadyCreated2If the corresponding object has already been created, the current dependent object is not the object being created3. But the attribute is not the current object, circular dependencies are not established, relies on string already @ HTTPS://www.cnblogs.com/qinzj/p/11485018.html
Copy the code
M173_05 doCreateBean source
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// Step 1: Prepare BeanWrapper. BeanWrapper is the wrapper for beans
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// If the singleton model is deleted from the never-completed FactoryBean cache
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// Enter the Bean creation process and create a BeanWrapper for the Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Get the wrapped instance object
final Object bean = instanceWrapper.getWrappedInstance();
// The type of the wrapped instance objectClass<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }// synchronized: synchronized: synchronized: synchronized: synchronized: synchronized
synchronized (mbd.postProcessingLock) {
if(! mbd.postProcessed) {try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException("...");
}
mbd.postProcessed = true; }}// Step 3: If it is a singleton and + is allowed to have circular dependencies, perform the singleton mode processing here
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Step 4: Init-Method -> PS:M173_05_03
Object exposedObject = bean;
try {
// Step 5: Attribute injection operation -> M173_30
populateBean(beanName, mbd, instanceWrapper);
// Step 6: Initialize the Bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException("..."); }}// In the case of a cyclic dependency, the initial dependency bean is recursed, returning an empty object for cyclic processing
// Return the earlier object or getDependentBeans recursively owned -> PS:M173_05_01
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if(earlySingletonReference ! =null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if(! actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException("..."); }}}}// Step 7: Register the Bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException("...");
}
return exposedObject;
}
Copy the code
conclusion
There are several anchor points:
Step 1: Entry
If there is one in the cache, it will be used directly. If not, it will use different ways to obtain a Bean from different Scope
- C171- AbstractBeanFactory
- M171_02- doGetBean
Copy the code
Step 2: Create the main process
Creating the main process is to create a complete Bean and go through the entire cycle of Bean creation, including process, property injection, init initialization, etc., which we will discuss in more detail in a later article
// Step 1 :
C173- AbstractAutowireCapableBeanFactory
M173_02- createBea
// Step 2 :
C173- AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
M173_05- doCreateBean
Copy the code
The appendix
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// Phase 1: Generate a beanName and try to get it from the singleton cache
final String beanName = transformedBeanName(name);
Object bean;
// get a Bean in singleton mode, loop dependency is the process of processing -> -> PS:M171_02_02
Object sharedInstance = getSingleton(beanName);
if(sharedInstance ! =null && args == null) {
// Get the Bean directly from the instantiation
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Phase 2: after the singleton cache fails to obtain
if (isPrototypeCurrentlyInCreation(beanName)) {
// Throw an exception if the pattern is archetypal and there are circular dependencies
throw new BeanCurrentlyInCreationException(beanName);
}
// Check whether there are bean definitions in the factory
BeanFactory parentBeanFactory = getParentBeanFactory();
Return -> PS:M171_02_03 -> PS:M171_02_03
if(parentBeanFactory ! =null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if(args ! =null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if(requiredType ! =null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return(T) parentBeanFactory.getBean(nameToLookup); }}// If the instance is fetched for type checking, but not actually used, mark the specified bean as already created -> PS:M171_02_04
if(! typeCheckOnly) { markBeanAsCreated(beanName); }try {
// RootBeanDefinition gets and checks LV171_001
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Phase 3: dependency check to ensure that the current bean depends on the initialized bean
// For the attribute LV171_001: MBD, get all dependencies via getDependsOn
String[] dependsOn = mbd.getDependsOn();
if(dependsOn ! =null) {
// Loop through all dependencies, recursively calling registerDependentBean + getBean
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw newBeanCreationException(.....) ; } registerDependentBean(dep, beanName);try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw newBeanCreationException(.....) ; }}}Phase 4: Three different types get Bean instances
// Create a Bean -> PS:M171_02_05
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throwex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally{ afterPrototypeCreation(beanName); }}); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); }catch (IllegalStateException ex) {
throw newBeanCreationException(....) ; }}}catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throwex; }}// Stage 5: The Bean is now ready. This is where you check to see if the required type matches the type of the actual Bean instance
// If the instances do not match, the conversion is required, and the conversion is returned directly
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) {
throw newBeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); }}// If not, return the original Bean
return (T) bean;
}
Copy the code
Reference and Thanks
Before writing this, I ran over and read it again. I am very grateful to the Deadknock series for opening the IOC source code learning
– > @ topjava. Cn/article / 139…