[Spring Topic] Source Code Analysis of Bean Life Cycle in Spring——Phase Two (1) (Instantiation of IOC)

foreword

reading preparation

Since the Spring source code analysis is a process with a strong front-to-back relationship, and the analysis here is also explained in the order of the code, so if you do not understand the pre-knowledge, there is a high probability that you will not be able to understand the current content. Therefore, it is especially recommended to read my previous articles (from top to bottom):

(PS: Especially "Bean's Life Cycle Flowchart", to help you [open your eyes] and understand the process first. After all, [understanding the code through the business is much easier than understanding the business through the code]!!!!)
(PS: Especially "Bean's Life Cycle Flowchart", to help you [open your eyes] and understand the process first. After all, [understanding the code through the business is much easier than understanding the business through the code]!!!!)
(PS: Especially "Bean's Life Cycle Flowchart", to help you [open your eyes] and understand the process first. After all, [understanding the code through the business is much easier than understanding the business through the code]!!!!)

reading guide

We have already mentioned it in the last lesson. The general entry point of this Spring source code analysis is new AnnotationConfigApplicationContext("org.tuling.spring");, so I won’t repeat the explanation here. What I want to talk about in this lesson is the instantiation of SpringIOC. Let’s directly give the entrance here. The call chain is as follows: (The call chain is relatively deep, don't get entangled in details

  1. AbstractApplicationContext#refresh: Refresh method, don't care
  2. AbstractApplicationContext#finishBeanFactoryInitialization: All remaining (non lazy-init) singletons are instantiated here
  3. DefaultListableBeanFactory#preInstantiateSingletons: Instantiate all remaining (non lazy-init) singletons here (the above method, the core working method is here)
  4. DefaultListableBeanFactory#getBean: method to get Bean
  5. AbstractBeanFactory#doGetBean: returns an instance of the specified bean, which can be shared or independent
  6. AbstractBeanFactory#doGetBeanThe callback method written by a partial code in the above is as follows:
	// 如果是单例创建bean实例
	if (mbd.isSingleton()) {
    
    
		sharedInstance = getSingleton(beanName, () -> {
    
    
			try {
    
    
				return createBean(beanName, mbd, args);
			}
			catch (BeansException ex) {
    
    
				// Explicitly remove instance from singleton cache: It might have been put there
				// eagerly by the creation process, to allow for circular reference resolution.
				// Also remove any beans that received a temporary reference to the bean.
				destroySingleton(beanName);
				throw ex;
			}
		});
		beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	}
  1. AbstractAutowireCapableBeanFactory#createBean: The central method of this class: create a bean instance, populate the bean instance, apply post-processors, etc.

As shown in the call chain above, the last method is the core method we will study this time. And through the comments, I think everyone has seen that this method not only does the work of instantiation, but also attributes filling, various post-processors, etc. (PS: Haha, students, I know that this [instantiation] call chain is quite deep, but don’t worry, just remember [don’t get entangled in those details] then everything is OK, we just follow the main line to study honestly, After all, these are the core)

reading advice

  1. Look at the source code, remember to get entangled in the details, otherwise it is easy to get stuck. Normally, just look at the main process
  2. If you don't understand, look at class annotations or method annotations. Spring is such an excellent source code, the annotations are really in place
  3. If you are an idea user, use the bookmark function of F11 more.
    • Ctrl + F11 Select files/folders, use mnemonics to set/cancel bookmarks (required)
    • Shift + F11 Pop-up bookmark display layer (required)
    • Ctrl +1,2,3...9 Locate to the bookmark position of the corresponding value (required)

Course content

1. Instantiation of Spring IOC

The [instantiation] mentioned here refers to the instantiation of a singleton, the prototype prototypenot included

1.1 Brief review

Do you know what the instantiation process is like? Ha, I know most of my classmates probably won't know. So, I hope that everyone really has to read " Bean's Declaration Cycle Flowchart ", because [understanding the business through code] is far more difficult than [understanding the code through the business]! Just look at the picture, at least we need to know [what the instantiation does and what are the steps], so that we can study it better.
insert image description here

As shown in the figure above, instantiation includes: merging BeanDefinition, loading class, before instantiation, inferring construction method, instantiation, post-processing of BeanDefinition, after instantiation, etc., these key steps. This is the core of our research in this article! !

1.2 Concept review

In this [instantiation] process, some concepts of Spring’s underlying design were involved. I roughly introduced some explanations of Spring’s underlying concepts in the last note.
The main concepts involved are:

  • BeanDefinition (design drawing): BeanDefinition represents the Bean definition, and there are many attributes in BeanDefinition to describe the characteristics of a Bean
  • BeanPostProcessor (an important extension point of Spring): Bean's post-processor, which performs expansion operations on Bean. As we said earlier, BeanPostProcessortwo extension methods are provided [before/after initialization]. But here, Spring has made a lot of expansions to this interface, and added some inherited BeanPostProcessorsubclasses or subinterfaces. In the instantiation phase, the main interfaces used are as follows:
    • InstantiationAwareBeanPostProcessor, the literal translation is: Bean post-processors that can perceive instantiation. And this inherits from BeanPostProcessor, obviously also has these two extension methods [before/after initialization]. In addition, InstantiationAwareBeanPostProcessoreveryone can guess the name passed, it must have the ability to expand the [instantiation] stage. The interface is defined in the following.
    • SmartInstantiationAwareBeanPostProcessor: The literal translation is: intelligent, instantiated Bean post-processors. In this interface, InstantiationAwareBeanPostProcessorthe interface is extended and several functions are added, including the implementation of the inferred structure. Also, this is an interface used internally by the framework. The interface is defined in the following.
    • MergedBeanDefinitionPostProcessor: The literal translation is: merge the post-processor of BeanDefinition. Post-processor callback interface used by the runtime to merge bean definitions. The interface is defined in the following.

The InstantiationAwareBeanPostProcessor interface is defined as follows:

/**
 * BeanPostProcessor的子接口,用于添加实例化前回调,以及实例化后但显式属性设置或自动生成之前的回调。
 * 通常用于抑制特定目标bean的默认实例化,例如创建具有特殊TargetSources的代理(池化目标、惰性初始化目标等),或者实现额外的注入策略,如字段注入。
 * 注:此接口为专用接口,主要供框架内部使用。建议尽可能实现普通的BeanPostProcessor接口。
 * 自:
 * 1.2
 * 参见:
 * org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.setCustomTargetSourceCreators, org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator
 * 作者:
 * 于尔根·霍勒,罗德·约翰逊
 */
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    
    

	/**
	 * 在目标bean实例化之前应用这个BeanPostProcessor。返回的bean对象可能是要使用的代理而不是目标bean,从而有效地抑制目标bean的默认实例化。
	 * 如果此方法返回一个非空对象,则bean创建过程将会中断。应用的唯一进一步处理是来自配置的BeanPostProcessors的postProcessAfterInitialization回调。
	 * 这个回调将应用于带有bean类的bean定义,以及工厂方法定义,在这种情况下,返回的bean类型将在这里传递。
	 * 后置处理器可以实现扩展的SmartInstantiationAwareBeanPostProcessor接口,以便预测它们将在这里返回的bean对象的类型。
	 * 默认实现返回null。
	 * 参数:
	 * beanClass——要实例化的bean的类
	 * beanName—bean的名称
	 * 返回:
	 * 要公开的bean对象,而不是目标bean的默认实例,或者为空,继续进行默认实例化
	 * 抛出:
	 * BeansException -在错误的情况下
	 * 参见:
	 * postProcessAfterInstantiation, org.springframework.beans.factory.support.AbstractBeanDefinition.getBeanClass(), org.springframework.beans.factory.support.AbstractBeanDefinition.getFactoryMethodName()
	 */
	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    
    
		return null;
	}

	/**
	 * 在bean通过构造函数或工厂方法实例化之后,但在Spring属性填充(来自显式属性或自动装配)发生之前执行操作。
	 * 这是在Spring自动装配开始之前对给定bean实例执行自定义字段注入的理想回调。
	 * 默认实现返回true。
	 * 参数:
	 * Bean—已创建的Bean实例,其属性尚未设置
	 * beanName—bean的名称
	 * 返回:
	 * 如果应该在bean上设置属性,则为True;如果应该跳过属性人口,则为False。正常的实现应该返回true。返回false还将阻止在此bean实例上调用任何后续的InstantiationAwareBeanPostProcessor实例。
	 * 抛出:
	 * BeansException -在错误的情况下
	 * 参见:
	 * postProcessBeforeInstantiation
	 */
	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    
    
		return true;
	}

	/**
	 * 在工厂将给定的属性值应用到给定的bean之前,对它们进行后处理,不需要任何属性描述符。
	 * 如果实现提供自定义postProcessPropertyValues实现,则应该返回null(默认值),否则则返回pvs。在该接口的未来版本中(删除了postProcessPropertyValues),默认实现将直接返回给定的pv。
	 * 参数:
	 * PVS—工厂将要应用的属性值(永远不会为空)
	 * bean——已创建的bean实例,但其属性尚未设置
	 * beanName—bean的名称
	 * 返回:
	 * 应用于给定bean的实际属性值(可以是传入的PropertyValues实例),或者null,它继续处理现有属性,但特别地继续调用postProcessPropertyValues(需要为当前bean类初始化PropertyDescriptors)。
	 * 抛出:
	 * BeansException -在错误的情况下
	 * 自:
	 * 5.1
	 * 参见:
	 * postProcessPropertyValues
	 */
	@Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
			throws BeansException {
    
    

		return null;
	}

	/**
	 * 在工厂将给定属性值应用到给定bean之前,对它们进行后处理。允许检查是否满足所有依赖项,例如基于bean属性设置器上的“Required”注释。
	 * 还允许替换要应用的属性值,通常通过基于原始PropertyValues创建新的MutablePropertyValues实例,添加或删除特定值。
	 * 默认实现按原样返回给定的pv。
	 * 弃用
	 * 从5.1开始,支持postProcessProperties(PropertyValues, Object, String)
	 * 参数:
	 * PVS—工厂将要应用的属性值(永远不会为空)
	 * PDS——目标bean的相关属性描述符(忽略了依赖类型——工厂专门处理的依赖类型——已经过滤掉了)
	 * bean——已创建的bean实例,但其属性尚未设置
	 * beanName—bean的名称
	 * 返回:
	 * 应用于给定bean的实际属性值(可以是传入的PropertyValues实例),或者为null以跳过属性填充
	 * 抛出:
	 * BeansException -在错误的情况下
	 * 参见:
	 * postProcessProperties, org.springframework.beans.MutablePropertyValues
	 */
	@Deprecated
	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    
    

		return pvs;
	}
}

The SmartInstantiationAwareBeanPostProcessor interface is defined as follows:

/**
 *  扩展了InstantiationAwareBeanPostProcessor接口,添加了一个回调函数,用于预测被处理bean的最终类型。
 * 注:此接口为专用接口,主要供框架内部使用。一般来说,应用程序提供的后处理器应该简单地实现普通的BeanPostProcessor接口,或者从InstantiationAwareBeanPostProcessorAdapter类派生。即使在点发布版本中,也可能向该接口添加新方法。
 * 自:
 * 2.0.3
 * 参见:
 * InstantiationAwareBeanPostProcessorAdapter
 * 作者:
 * Juergen hoel
 */
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
    
    

	/**
	 * 预测这个处理器的postProcessBeforeInstantiation回调最终返回的bean的类型。
	 * 默认实现返回null。
	 * 参数:
	 * beanClass—bean的原始类beanName—bean的名称
	 * 返回:
	 * bean的类型,如果不可预测,则为空
	 * 抛出:
	 * BeansException -在错误的情况下
	 */
	@Nullable
	default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
    
    
		return null;
	}

	/**
	 * 确定要为给定bean使用的候选构造函数。
	 * 默认实现返回null。
	 * 参数:
	 * beanClass—bean的原始类(不为空)beanName—bean的名称
	 * 返回:
	 * 候选构造函数,如果未指定,则为空
	 * 抛出:
	 * BeansException -在错误的情况下
	 */
	@Nullable
	default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
			throws BeansException {
    
    

		return null;
	}

	/**
	 * 获取对指定bean的早期访问的引用,通常是为了解析循环引用。
	 * 这个回调让后处理器有机会尽早公开包装器——也就是说,在目标bean实例完全初始化之前。暴露的对象应该等同于postProcessBeforeInitialization / postProcessAfterInitialization所暴露的对象。请注意,此方法返回的对象将用作bean引用,除非后处理器返回与所述后处理回调不同的包装器。换句话说:那些处理后回调可能最终公开相同的引用,或者返回那些后续回调的原始bean实例(如果受影响的bean的包装器已经为对该方法的调用构建了,那么默认情况下它将作为最终bean引用公开)。
	 * 默认实现按原样返回给定的bean。
	 * 参数:
	 * bean—原始bean实例beanName—bean的名称
	 * 返回:
	 * 要作为bean引用公开的对象(通常将传入的bean实例作为默认值)
	 * 抛出:
	 * BeansException -在错误的情况下
	 */
	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
    
    
		return bean;
	}
}

The MergedBeanDefinitionPostProcessor interface is defined as follows:

/**
 * 运行时用于合并bean定义的后处理器回调接口。BeanPostProcessor实现可以实现这个子接口,以便对合并的bean定义(原始bean定义的处理副本)进行后处理,Spring BeanFactory使用合并的bean定义来创建bean实例。
 * 例如,postProcessMergedBeanDefinition方法可以对bean定义进行内省,以便在对bean的实际实例进行后处理之前准备一些缓存的元数据。也允许修改bean定义,但只允许修改用于并发修改的定义属性。本质上,这只适用于在RootBeanDefinition本身上定义的操作,而不适用于其基类的属性。
 * 自:
 * 2.5
 * 参见:
 * org.springframework.beans.factory.config.ConfigurableBeanFactory.getMergedBeanDefinition
 * 作者:
 * Juergen hoel
 */
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
    
    

	/**
	 * 对指定bean的给定合并bean定义进行后处理。
	 * 参数:
	 * beanDefinition—为bean合并的bean定义beanType—托管bean实例的实际类型beanName—bean的名称
	 * 参见:
	 * AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors
	 */
	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

	/**
	 * 通知指定名称的bean定义已被重置,并且此后处理器应清除受影响bean的所有元数据。
	 * 默认实现为空。
	 * 参数:
	 * beanName—bean的名称
	 * 自:
	 * 5.1
	 * 参见:
	 * DefaultListableBeanFactory.resetBeanDefinition
	 */
	default void resetBeanDefinition(String beanName) {
    
    
	}
}

There is still one thing I want to remind everyone here, BeanPostProcessorwhich is defined by Spring as a [hook], and hooks are often used to change the original behavior of the system. This change is usually reflected in: the impact on the Bean life cycle, or the change of an object completed in a certain life cycle, and so on. (It’s a bit obscure to say this, but in layman’s terms: Bean may not go through a complete life cycle, for example, after [before instantiation], it directly jumps to [after initialization], without going through the original definition of [instantiation], [After instantiation], [Other post-processing], etc.; or, the original initialization action is done by Spring for me, but because of our own intervention, Spring does not initialize for us, but according to the programmer's wishes)

Article link:
" [Spring Topic] Analysis of the Core Concepts of Spring's Underlying Architecture "

1.3 Explanation of core methods

The backbone process of the entire IOC instantiation mainly involves [2 classes, 11 core methods]. Below, we will explain each method in turn according to the calling order.

2. Method explanation

As we said above, the instantiation process here includes key steps such as merging BeanDefinition, loading classes, before instantiation, inferring construction methods, instantiation, post-processing of BeanDefinition, and after instantiation. Therefore, in the entire call chain, these things are basically done.
As we said earlier, the instantiation code entry this time is as follows:

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

2.1 AbstractBeanFactory#getMergedLocalBeanDefinition:合并BeanDefinition


Method call chain: full path called in AbstractBeanFactory#doGetBean : org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition
method comment: return the merged RootBeanDefinition, if the specified bean corresponds to the child bean definition, traverse the parent bean definition.

We mentioned this at the end of the last class, so I won’t repeat it here, but it is counted in the instantiation process, hehe

2.2 AbstractAutowireCapableBeanFactory#createBean:创建Bean


Method call chain: full path called in AbstractBeanFactory#doGetBean : org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
method annotation: the central method of this class: create a bean instance, populate the bean instance, apply post-processor, etc. wait.

The source code is as follows:

	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    
    

		if (logger.isTraceEnabled()) {
    
    
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// 步骤一:加载类
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    
    
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// 不用管这个
		try {
    
    
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
    
    
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
    
    
			// 步骤二:实例化前
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
    
    
				return bean;
			}
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
    
    
			// 步骤三:创建Bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
    
    
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    
    
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
    
    
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

Interpretation of the method: The above code is long and trt-catchtakes up half of it, ahaha. There are only three steps here, which will be mentioned below.

  1. resolveBeanClass: load class
  2. resolveBeforeInstantiation: before instantiation
  3. doCreateBean: where the Bean is actually created

2.3 AbstractAutowireCapableBeanFactory#resolveBeanClass: load class

PS: It’s not very important, it’s good to know that there is this step

Method call chain: called by createBean of 2.2
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeanClass
method comment: the central method of this class: create a bean instance, populate the bean instance, apply post-processor, etc. wait.

The source code is as follows:

protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
		throws CannotLoadBeanClassException {
    
    
	if (mbd.hasBeanClass()) {
    
    
		return mbd.getBeanClass();
	}
	if (System.getSecurityManager() != null) {
    
    
		return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
				() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
	}
	else {
    
    
		return doResolveBeanClass(mbd, typesToMatch);
	}
}

Interpretation of the method: the outer layer of this code is quite simple,Perhaps System.getSecurityManager() != nullit is more difficult for everyone to understand than this. This is a security manager inside Spring, which is often not enabled. There will be a lot of this kind of code later, anyway, if you encounter this, just look at elsethe logic directly. As for the source code of the inner layer, doResolveBeanClassit is as follows:

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

        // 步骤一:获取默认的类加载器
        ClassLoader beanClassLoader = getBeanClassLoader();
        ClassLoader dynamicLoader = beanClassLoader;
        boolean freshResolve = false;

        // 步骤二:在我们这个调用链上不会走这里,因为typesToMatch为null
        if (!ObjectUtils.isEmpty(typesToMatch)) {
    
    
            ClassLoader tempClassLoader = getTempClassLoader();
            if (tempClassLoader != null) {
    
    
                dynamicLoader = tempClassLoader;
                freshResolve = true;
                if (tempClassLoader instanceof DecoratingClassLoader) {
    
    
                    DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
                    for (Class<?> typeToMatch : typesToMatch) {
    
    
                        dcl.excludeClass(typeToMatch.getName());
                    }
                }
            }
        }

        // 步骤三
        String className = mbd.getBeanClassName();
        if (className != null) {
    
    

            // 步骤3.1:这里也不用怎么看,这是Spring表达式解析的东西。Spring表达式这个东西我们用的很少(类似EL表达式,这样来理解)
            Object evaluated = evaluateBeanDefinitionString(className, mbd);
            if (!className.equals(evaluated)) {
    
    
                if (evaluated instanceof Class) {
    
    
                    return (Class<?>) evaluated;
                }
                else if (evaluated instanceof String) {
    
    
                    className = (String) evaluated;
                    freshResolve = true;
                }
                else {
    
    
                    throw new IllegalStateException("Invalid class name expression result: " + evaluated);
                }
            }
            if (freshResolve) {
    
    
                if (dynamicLoader != null) {
    
    
                    try {
    
    

                        // 步骤3.2 加载类
                        return dynamicLoader.loadClass(className);
                    }
                    catch (ClassNotFoundException ex) {
    
    
                        if (logger.isTraceEnabled()) {
    
    
                            logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
                        }
                    }
                }
                return ClassUtils.forName(className, dynamicLoader);
            }
        }

        // 步骤四:正常来说走的是这里。使用默认的类加载器加载类
        return mbd.resolveBeanClass(beanClassLoader);
    }

Interpretation of the method: Here, it is roughly divided into 4 steps. The first step is to obtain the class loader, and you will find that ClassUtils.getDefaultClassLoader()the method is actually called when you trace it inside. The code inside is quite simple, and the acquisition principles are as follows: ( It takes a little JVM knowledge to understand, and it doesn’t matter if you don’t understand it )

  1. Prioritize returning the ClassLoader in the current thread
  2. When the class loader in the thread is null, return the class loader of the ClassUtils class
  3. If the class loader of the ClassUtils class is empty, it means the ClassUtils class loaded by the Bootstrap class loader, then return the system class loader

Step 2 is the first one if. In our call chain, it will not come in here because typeToMatchit is null;
Step 3, you can see it or not, and generally it will not come in here. This is what Spring expressions parse. I guess most people have never used Spring expressions... (similar to EL expressions, understand this way)
Step 4, normally it will be executed here, and then class loading will be performed here, and the class object will be obtained through reflection , the code looks like this:

	public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
    
    
		String className = getBeanClassName();
		if (className == null) {
    
    
			return null;
		}
		Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
		this.beanClass = resolvedClass;
		return resolvedClass;
	}

*2.4 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation: [before instantiation] entry

(PS:Finally came here, this is the core test point

Method call chain: called by createBean in 2.2
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
method comment: apply the post-processor before instantiation, and resolve whether the specified bean has a shortcut before instantiation.

The source code is as follows:

	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    
    
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    
    
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
    
    
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
    
    
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

Method interpretation: the code is just a few lines. First pass hasInstantiationAwareBeanPostProcessorsto see if there is InstantiationAwareBeanPostProcessors. If yes, call the corresponding [before instantiation] method, that is applyBeanPostProcessorsBeforeInstantiation(This is the real place to work, which will be introduced later)。

There is a detail here, that is, applyBeanPostProcessorsBeforeInstantiationif the returned object is not empty, the applyBeanPostProcessorsAfterInitialization[after initialization] method of the bean is called directly. this meansThe life cycle of the bean is changed! ! Moreover, if the Bean here has a value, the outer layer directly returns that the creation is successful, and it will not continue down, as shown below: (2.2 createBean call code)

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
    
    
	return bean;
}

2.5 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation: [before instantiation] the real work place

Method call chain: called by resolveBeforeInstantiation of 2.4
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
method annotation: apply InstantiationAwareBeanPostProcessors to the specified bean definition (by class and name), and call their postProcessB eforeInstantiation method. If the return is not empty, there is no need for Spring to instantiate it for us

The source code is as follows:

	@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    
    
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    
    
			Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
			if (result != null) {
    
    
				return result;
			}
		}
		return null;
	}

Method interpretation:InstantiationAwareBeanPostProcessorHere is finally the core of what we said before.. The old way, traverse all InstantiationAwareBeanPostProcessor, and then call postProcessBeforeInstantiation(). Here, as long as one is found and InstantiationAwareBeanPostProcessorthe postProcessBeforeInstantiation()return is not empty, the traversal will be stopped directly.
The implicit meaning of this method is: before Spring helps us instantiate, Spring will first look for it to see if the user has his own instantiation ideas for the class corresponding to the current beanName. If so, Spring will not help us. created.

2.6 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization: The first possible call [after initialization]

Method call chain: called by resolveBeforeInstantiation of 2.4
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
method comment: method after application initialization. Usually when this method is called, it is considered that the properties have been filled, initialized, etc.

The source code is as follows:

	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {
    
    

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
    
    
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
    
    
				return result;
			}
			result = current;
		}
		return result;
	}

Interpretation of the method: Look, all BeanPostProcessor the interfaces are directly obtained here, and then postProcessAfterInitialization()the method is applied. There is an empty judgment here, which is required by the interface. Returning null means that you do not want to continue executing the rest of BeanPostProcessor the interface

2.7 AbstractAutowireCapableBeanFactory#doCreateBean: [Instantiation] entry (including subsequent instantiation process)

Method call chain: called by createBean in 2.2
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
method comment: The central method of the AbstractAutowireCapableBeanFactory class: create a bean instance, fill the bean instance, apply the post-processor, etc.

The source code is very long, so I won't intercept it. In this method, four things are mainly done:

  1. Instantiate (infer constructor, instantiate)
  2. Post-processing of BeanDefinition
  3. Attribute injection (after instantiation, attribute injection) (yes, you read that right, [after instantiation] is called in the method of attribute injection)
  4. initialization

Method interpretation: As the method comment says, here [create a bean instance, populate the bean instance, apply the post-processor] and so on. This means that the remaining ==[inferred construction method, instantiation, post-processing of BeanDefinition, post-instantiation, etc.]== steps in the [instantiation] process are included here. in addition,The next chapter will talk about [IOC attribute filling], [IOC-Aware callback], [IOC initialization] and other stage entries are actually in this method

*2.8 AbstractAutowireCapableBeanFactory#createBeanInstance: instantiation

Method call chain: called by doCreateBean of 2.7
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
method comment: The central method of the AbstractAutowireCapableBeanFactory class: create a bean instance, fill the bean instance, apply the post-processor, etc.

The source code is as follows:

 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    
    
        // 步骤一:再次确保类已经被加载
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

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

        // 步骤二:使用Supplier创建对象
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
    
    
            return obtainFromSupplier(instanceSupplier, beanName);
        }

        // 步骤三:工厂方法创建对象
        if (mbd.getFactoryMethodName() != null) {
    
    
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
    
    
            synchronized (mbd.constructorArgumentLock) {
    
    
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
    
    
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) {
    
    
            if (autowireNecessary) {
    
    
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
    
    
                return instantiateBean(beanName, mbd);
            }
        }

        // 步骤四:推断构造方法
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    
    
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // Preferred constructors for default construction?
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
    
    
            return autowireConstructor(beanName, mbd, ctors, null);
        }

        // 步骤五:实例化
        return instantiateBean(beanName, mbd);
    }

Interpretation of the method: Here, when instantiating the bean, various methods are used. like:

2.8.1 Supplier creation object

Supplier, literal translation: supplier.
First determine whether the Supplier is set in the BeanDefinition, and if it is set, call the get() of the Supplier to get the object. You have to directly use the BeanDefinition object to set the Supplier, for example:

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
    
    
 @Override
 public Object get() {
    
    
  return new UserService();
 }
});
context.registerBeanDefinition("userService", beanDefinition);

2.8.2 Factory method to create objects

If the Supplier is not set, check whether the factoryMethod is set in the BeanDefinition, which is the factory method,There are two ways to set factoryMethod, for example:
Method 1:

<bean id="userService" class="com.zhouyu.service.UserService" factory-method="createUserService" />

The corresponding UserService class is:

public class UserService {
    
    

 public static UserService createUserService() {
    
    
  System.out.println("执行createUserService()");
  UserService userService = new UserService();
  return userService;
 }

 public void test() {
    
    
  System.out.println("test");
 }

}

Method 2:

<bean id="commonService" class="com.zhouyu.service.CommonService"/>
<bean id="userService1" factory-bean="commonService" factory-method="createUserService" />

The corresponding CommonService class is:

public class CommonService {
    
    

 public UserService createUserService() {
    
    
  return new UserService();
 }
}

After Spring finds that the current BeanDefinition method sets the factory method, it will distinguish between the two methods, and then call the factory method to get the object.
It is worth noting that the BeanDefinition we define through @Bean has factoryMethod and factoryBean, which is very similar to the above method 2. The method annotated by @Bean is factoryMethod, and the AppConfig object is factoryBean. If the method annotated by @Bean is static, then the corresponding method is one.

2.8.3 Constructors create objects

RT。

2.9 AbstractAutowireCapableBeanFactory#autowireConstructor: Infer construction method

Method call chain: called by createBeanInstance of 2.7
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor
method comment: Infer the constructor and create the object.

The code is so long, I won't intercept it. The code here is fine whether you look at it or not, the main thing is to understand the process and principles.

  1. If a class has only one constructor, regardless of whether the constructor has parameters or no parameters, Spring will use this constructor to create the object
  2. If there are multiple construction methods, see if there is a no-argument construction method. Because the no-argument construction method has a default meaning, if so, choose the no-argument construction method to create the object;
  3. If there are multiple construction methods, and there are no parameters, check whether there is an @Autowired annotation on the construction method, choose if there is one, and report an error if there is no

In addition, in the logic of inferring the construction method, in addition to selecting the construction method and finding the input object, it will also determine whether there is a method using the **@Lookup annotation** in the corresponding class. If it exists, encapsulate this method as a LookupOverride object and add it to the BeanDefinition.

When instantiating, if it is judged that there is no LookupOverride in the current BeanDefinition, then directly use the constructor reflection to obtain an instance object. If there is a LookupOverride object, that is, there is a @Lookup annotated method in the class, a proxy object will be generated.
The @Lookup annotation is method injection, using the demo as follows:

@Component
public class UserService {
    
    

 private OrderService orderService;

 public void test() {
    
    
  OrderService orderService = createOrderService();
  System.out.println(orderService);
 }

 @Lookup("orderService")
 public OrderService createOrderService() {
    
    
  return null;
 }

}

2.10 AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors: BeanDefinition post-processing

Method call chain: called by doCreateBean of 2.7
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
Method Note: Apply MergedBeanDefinitionPostProcessors to specified bean definitions and call their postProcessMergedBeanDefinition method.

The source code is as follows:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    
    
		for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
    
    
			processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
		}
	}

Method interpretation: After the Bean object is instantiated, the next step is to assign values ​​to the properties of the object. Before actually assigning a value to the property, Spring provides another extension point, the current one MergedBeanDefinitionPostProcessors. The main difficulty here is that this type of BeanPostProcessorapplication scenario may be what everyone is more concerned about. So what do you think is the main application scenario here? In fact, according to Spring's life cycle, the extension point it provides you now can only be the life cycle after the [instantiation] stage. After all, what has happened in the past can no longer be changed. Therefore, we can intervene in the [initialization] stage here, as shown in the following example:

public static void main(String[] args) {
    
    
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
      Object newUser = context.getBean("user");
      System.out.println(newUser);
}

// 声明bean
@Component
public class User {
    
    
    private String name;

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public void myInit() {
    
    
        System.out.println("这是我自己指定的初始化方法");
    }
}

// 声明一个MergedBeanDefinitionPostProcessor,然后改变了User这个Bean的初始化方法
@Component
public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
    
    
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    
    
        if (beanName.equals("user")) {
    
    
            beanDefinition.setInitMethodName("myInit");
        }
    }
}

PS: In the Spring source code, this post-processor has a very important usage scenario, which is [Find injection point] in SpringIOC [Dependency Injection]. Two implementation classes of the post-processor will be used here, AutowiredAnnotationBeanPostProcessorand CommonAnnotationBeanPostProcessorare used to implement the logic of @Autowired and @Resource [finding injection points] respectively, and cache them in a Map of the object (injectionMetadataCache) for dependency injection. Prepare.

2.11 AbstractAutowireCapableBeanFactory#populateBean: attribute injection (including: after instantiation)

(PS: Attribute injection is not what we need to pay attention to here, but because [after instantiation] is in this method, so we can only click in)

Method call chain: called by doCreateBean of 2.7
Full path: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
method annotation: use the property value from the bean definition to populate the bean instance in the given BeanWrapper (property filling/dependency injection).

The key source code in populateBean is as follows:

	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    
    
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    
    
					return;
				}
			}
		}

Interpretation of the method: After processing the BeanDefinition, Spring designed an extension point: InstantiationAwareBeanPostProcessoryes postProcessAfterInstantiation(), for example:

@Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    
    

 @Override
 public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    
    

  if ("userService".equals(beanName)) {
    
    
   UserService userService = (UserService) bean;
   userService.test();
  }

  return true;
 }
}

The above code is to process the object instantiated by userService. This extension point is basically not used in the Spring source code. It is estimated that it is in preparation for future expansion.

After method summary

I may not write like this in the future, it is very troublesome. The reason why I circle the key methods and links like this is purely to deepen my impression, and I don’t know if I can release it for everyone to see, whether you can learn anything.

3. Instantiation logic flow chart

insert image description here

summarize

  1. Learned the process of instantiation
  2. Learned 2 kinds of [Bean post-processors] used in the instantiation process: InstantiationAwareBeanPostProcessorand MergedBeanDefinitionPostProcessorsome of their internal methods

Guess you like

Origin blog.csdn.net/qq_32681589/article/details/132265726