【Spring专题】Spring之Bean的生命周期源码解析——阶段二(IOC之实例化)

目录

  • 前言
    • 阅读准备
    • 阅读指引
    • 阅读建议
  • 课程内容
    • 一、SpringIOC之实例化
      • 1.1 简单回顾
      • 1.2 概念回顾
      • 1.3 核心方法讲解
    • 二、方法讲解
      • 2.1 AbstractBeanFactory#getMergedLocalBeanDefinition:合并BeanDefinition
      • 2.2 AbstractAutowireCapableBeanFactory#createBean:创建Bean
      • 2.3 AbstractAutowireCapableBeanFactory#resolveBeanClass:加载类
      • *2.4 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation:【实例化前】入口
      • 2.5 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation:【实例化前】真正干活的地方
      • 2.6 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization:第一次可能调用【初始化后】
      • 2.7 AbstractAutowireCapableBeanFactory#doCreateBean:【实例化】入口(包括后续的实例化过程)
      • *2.8 AbstractAutowireCapableBeanFactory#createBeanInstance:实例化
        • 2.8.1 Supplier创建对象
        • 2.8.2 工厂方法创建对象
        • 2.8.3 构造方法创建对象
      • 2.9 AbstractAutowireCapableBeanFactory#autowireConstructor:推断构造方法
      • 2.10 AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors:BeanDefinition后置处理
      • 2.11 AbstractAutowireCapableBeanFactory#populateBean:属性注入(包含:实例化后)
      • 方法总结后
    • 三、实例化逻辑流程图
  • 学习总结

前言

阅读准备

由于Spring源码分析是一个前后联系比较强的过程,而且这边分析,也是按照代码顺序讲解的,所以不了解前置知识的情况下,大概率没办法看懂当前的内容。所以,特别推荐看看我前面的文章(自上而下次序):

  • Spring底层核心原理解析【学习难度:★★☆☆☆
  • 手写简易Spring容器过程分析【学习难度:★★☆☆☆
  • Spring之底层架构核心概念解析【学习难度:★★★☆☆,重要程度:★★★★★
  • Bean的生命周期流程图【学习难度:☆☆☆☆☆,重要程度:★★★★★
  • Spring之Bean的生命周期源码解析——阶段一(扫描生成BeanDefinition)

(PS:特别是《Bean的生命周期流程图》,帮大家【开天眼】,先了解下流程。毕竟【通过业务了解代码,远比通过代码了解业务简单的多】!!!!)
(PS:特别是《Bean的生命周期流程图》,帮大家【开天眼】,先了解下流程。毕竟【通过业务了解代码,远比通过代码了解业务简单的多】!!!!)
(PS:特别是《Bean的生命周期流程图》,帮大家【开天眼】,先了解下流程。毕竟【通过业务了解代码,远比通过代码了解业务简单的多】!!!!)

阅读指引

我们在上一节课已经说到过了,本次Spring源码剖析的总入口是new AnnotationConfigApplicationContext("org.tuling.spring");,这里就不再重复解释了。本节课要说的内容,是SpringIOC的实例化,我们这里直接给到入口吧,调用链如下:(调用链比较深,不要纠结细枝末节

  1. AbstractApplicationContext#refresh:刷新方法,不用在意
  2. AbstractApplicationContext#finishBeanFactoryInitialization:在这里实例化所有剩余的(非lazy-init)单例
  3. DefaultListableBeanFactory#preInstantiateSingletons:在这里实例化所有剩余的(非lazy-init)单例(上面的方法,核心干活的方法就是这里)
  4. DefaultListableBeanFactory#getBean:获取Bean的方法
  5. AbstractBeanFactory#doGetBean:返回指定bean的一个实例,它可以是共享的,也可以是独立的
  6. 上面这个AbstractBeanFactory#doGetBean里面的一段局部代码写的回调方法,如下:
	// 如果是单例创建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:这个类的中心方法:创建一个bean实例,填充bean实例,应用后处理器,等等。

如上面的调用链所示,最后一个方法,才是我们本次要研究的核心方法。而且通过注释,我想大家也看到了,这个方法不单单干了实例化的工作,还有属性填充、各种后置处理器等。(PS:哈哈,同学们,我知道这个【实例化】调用链挺深的,但是大家不要烦恼,只要切记【不要纠结那些细枝末节】那一切都OK,我们老老实实地跟着主线来研究就好,毕竟这些才是核心)

阅读建议

  1. 看源码,切记纠结细枝末节,不然很容易陷进去。正常来说,看主要流程就好了
  2. 遇到不懂的,多看看类注释或者方法注释。Spring这种优秀源码,注释真的非常到位
  3. 如果你是idea用户,多用F11的书签功能。
    • Ctrl + F11 选中文件 / 文件夹,使用助记符设定 / 取消书签 (必备)
    • Shift + F11 弹出书签显示层 (必备)
    • Ctrl +1,2,3…9 定位到对应数值的书签位置 (必备)

课程内容

一、SpringIOC之实例化

这里说的【实例化】,是指单例的实例化,原型prototype不包含在内

1.1 简单回顾

大家知道,实例化的过程是怎样的吗?哈,我知道大部分的同学可能都不会知道。所以呢,我希望大家真的要有去看过《 Bean的声明周期流程图》,因为,通过【代码去理解业务】,远远比【通过业务理解代码】难得多!直接看个图吧,起码咱得知道【实例化到底干了什么,有哪些步骤】,我们才能更好的去研究。
在这里插入图片描述
如上图所示,实例化包含了:合并BeanDefinition、加载类、实例化之前、推断构造方法、实例化、BeanDefinition的后置处理、实例化后等,这些关键步骤。这就是我们本篇文章研究的核心!!

1.2 概念回顾

在这个【实例化】过程中,涉及到了一些Spring底层设计的概念,我在上一个笔记里面有大概介绍过Spring底层概念的一些讲解,不记得的同学记得回去翻一翻。
主要涉及的概念有:

  • BeanDefinition(设计图纸):BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特征
  • BeanPostProcessor(Spring重要的拓展点):Bean的后置处理器,对Bean做拓展操作。我们前面说过,BeanPostProcessor提供了【初始化前/后】两个拓展方法。但是这里,Spring内部对这个接口做了很多拓展,新增了一些继承自BeanPostProcessor的子类或者子接口。在实例化阶段,主要用到的接口如下:
    • InstantiationAwareBeanPostProcessor,直译过来就是:能感知实例化的Bean后置处理器。而这个继承自BeanPostProcessor,显然也具备这【初始化前/后】两个拓展方法。另外,通过InstantiationAwareBeanPostProcessor的名字大家也能猜到了,它肯定是具有对【实例化】阶段拓展的能力的。接口定义在后面。
    • SmartInstantiationAwareBeanPostProcessor:直译过来就是:智能的,能感知实例化的Bean后置处理器。在这个接口中,拓展了InstantiationAwareBeanPostProcessor接口,新增了几个函数,其中就包括了推断构造的实现。另外,这是一个框架内部使用接口。接口定义在后面。
    • MergedBeanDefinitionPostProcessor:直译过来就是:合并BeanDefinition的后置处理器。运行时用于合并bean定义的后处理器回调接口。接口定义在后面。

InstantiationAwareBeanPostProcessor接口定义如下:

/*** 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()*/@Nullabledefault 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*/@Nullabledefault 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@Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}
}

SmartInstantiationAwareBeanPostProcessor接口定义如下:

/***  扩展了InstantiationAwareBeanPostProcessor接口,添加了一个回调函数,用于预测被处理bean的最终类型。* 注:此接口为专用接口,主要供框架内部使用。一般来说,应用程序提供的后处理器应该简单地实现普通的BeanPostProcessor接口,或者从InstantiationAwareBeanPostProcessorAdapter类派生。即使在点发布版本中,也可能向该接口添加新方法。* 自:* 2.0.3* 参见:* InstantiationAwareBeanPostProcessorAdapter* 作者:* Juergen hoel*/
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {/*** 预测这个处理器的postProcessBeforeInstantiation回调最终返回的bean的类型。* 默认实现返回null。* 参数:* beanClass—bean的原始类beanName—bean的名称* 返回:* bean的类型,如果不可预测,则为空* 抛出:* BeansException -在错误的情况下*/@Nullabledefault Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {return null;}/*** 确定要为给定bean使用的候选构造函数。* 默认实现返回null。* 参数:* beanClass—bean的原始类(不为空)beanName—bean的名称* 返回:* 候选构造函数,如果未指定,则为空* 抛出:* BeansException -在错误的情况下*/@Nullabledefault 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;}
}

MergedBeanDefinitionPostProcessor接口定义如下:

/*** 运行时用于合并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) {}
}

这里还是有一点想要提醒各位的,BeanPostProcessor是被Spring定义为【钩子】的,而钩子,很多时候都是为了改变系统原有行为的。这种改变,通常体现在:对Bean生命周期的影响,或者某个生命周期完成对象的改变等等。(这么说有点晦涩难懂,通俗点讲就是:Bean可能不会经过完整生命周期,比如【实例化前】之后,直接就跳到【初始化后】了,没有经过原本定义的【实例化】、【实例化后】、【其他后置处理】等;或者,原本初始化动作是Spring帮我门完成的,但是由于我们自己介入了,Spring就不帮我们初始化了,而是按照程序员意愿)

文章链接:
《【Spring专题】Spring之底层架构核心概念解析》

1.3 核心方法讲解

整个IOC实例化的主干过程,主要涉及了【2个类,11个核心方法】。下面,我们将会按照调用次序,依次讲解各个方法。

二、方法讲解

我们在上面说到过,这里的实例化过程包含了:合并BeanDefinition、加载类、实例化之前、推断构造方法、实例化、BeanDefinition的后置处理、实例化后等关键步骤。所以,在整个调用链上,基本上就是干了这些事情。
我们前面说过,本次的实例化代码入口如下:

	// 如果是单例创建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

方法调用链:AbstractBeanFactory#doGetBean里面调用的
全路径:org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition
方法注释:返回合并的RootBeanDefinition,如果指定的bean对应于子bean定义,则遍历父bean定义。

我们在上节课最后的地方提到过这个,这边就不重复讲了,但是,他是算在实例化过程里面的,嘻嘻

2.2 AbstractAutowireCapableBeanFactory#createBean:创建Bean

方法调用链:AbstractBeanFactory#doGetBean里面调用的
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
方法注释:这个类的中心方法:创建一个bean实例,填充bean实例,应用后处理器,等等。

源码如下:

	@Overrideprotected 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 {// 步骤三:创建BeanObject 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);}}

方法解读:上面代码老长一段,trt-catch占了一半,啊哈哈。 这里面的步骤就三个,下面也会讲到。

  1. resolveBeanClass:加载类
  2. resolveBeforeInstantiation:实例化前
  3. doCreateBean:真正创建Bean的地方

2.3 AbstractAutowireCapableBeanFactory#resolveBeanClass:加载类

PS:不算很重要,知道有这个步骤就好

方法调用链:由2.2的createBean调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeanClass
方法注释:这个类的中心方法:创建一个bean实例,填充bean实例,应用后处理器,等等。

源码如下:

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

方法解读:这个代码外层挺简单的,也许大家对比System.getSecurityManager() != null这个比较难理解而已。这是Spring内部的一个安全管理器,很多时候都是不开启的。后面也会出现大量这种代码,反正遇到这个就直接看else的逻辑就好了。至于里层的doResolveBeanClass源码如下:

    private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)throws ClassNotFoundException {// 步骤一:获取默认的类加载器ClassLoader beanClassLoader = getBeanClassLoader();ClassLoader dynamicLoader = beanClassLoader;boolean freshResolve = false;// 步骤二:在我们这个调用链上不会走这里,因为typesToMatch为nullif (!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);}

方法解读:在这里,大体分为4个步骤。步骤一就是获取类加载器,往里追踪会发现,实际上调用的是ClassUtils.getDefaultClassLoader()方法。里面的代码挺简单的,获取原则如下:(需要一点JVM底子才懂,不了解也无所谓

  1. 优先返回当前线程中的ClassLoader
  2. 线程中类加载器为null的情况下,返回ClassUtils类的类加载器
  3. 如果ClassUtils类的类加载器为空,那么则表示是Bootstrap类加载器加载的ClassUtils类,那么则返回系统类加载器

步骤二,就是第一个if,在我们这里的调用链上是不会进来这里的,因为typeToMatch是null;
步骤三,可看可不看,一般也不会进来这里。这是Spring表达式解析的东西。Spring表达式这个东西我估计大部分人都没用过吧…(类似EL表达式,这样来理解)
步骤四,正常来说会执行到这里,然后在这里进行类加载,并且通过反射获得class对象,代码如下所示:

	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:【实例化前】入口

(PS:终于来到这里了,这才是核心考点

方法调用链:由2.2的createBean调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
方法注释:应用实例化前的后处理器,解析指定bean是否存在实例化前的快捷方式。

源码如下:

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

方法解读:代码短短的几行。首先通过hasInstantiationAwareBeanPostProcessors看看是否有InstantiationAwareBeanPostProcessors。有,则调用对应的【实例化前】方法,即applyBeanPostProcessorsBeforeInstantiation这里才是真正干活的地方,后面介绍)。

这里有一个细节,那就是applyBeanPostProcessorsBeforeInstantiation如果返回的对象不为空,则直接调用applyBeanPostProcessorsAfterInitialization走bean的【初始化后】方法了。这说明Bean的生命周期被改变!!而且,如果这里的Bean有值的话,外层直接返回创建成功了,不会继续往下走了,如下所示:(2.2的createBean调用处代码)

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

2.5 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation:【实例化前】真正干活的地方

方法调用链:由2.4的resolveBeforeInstantiation调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
方法注释:将InstantiationAwareBeanPostProcessors应用到指定的bean定义(通过类和名称),调用它们的postProcessBeforeInstantiation方法。如果返回不为空,则无需Spring帮我们实例化了

源码如下:

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

方法解读:这里终于出现我们之前说的核心InstantiationAwareBeanPostProcessor。老样子,遍历所有的InstantiationAwareBeanPostProcessor,然后调用postProcessBeforeInstantiation()。这里只要找到一个InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation()返回不为空,则直接停止遍历。
这个方法其实隐含的意思是:在Spring帮我们实例化之前,Spring会先去找找看,用户有没有对当前beanName对应的class有自己的实例化想法,如果有,则Spring就不帮我们创建了。

2.6 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization:第一次可能调用【初始化后】

方法调用链:由2.4的resolveBeforeInstantiation调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
方法注释:应用初始化后方法。通常调用此方法的时候,会认为已经经过了属性填充、初始化等

源码如下:

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

方法解读:看,这里直接获取所有BeanPostProcessor 接口,然后应用postProcessAfterInitialization()方法。这里有个空判断,是接口要求这么做的。返回null表示不想继续执行剩余的BeanPostProcessor 接口

2.7 AbstractAutowireCapableBeanFactory#doCreateBean:【实例化】入口(包括后续的实例化过程)

方法调用链:由2.2的createBean调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
方法注释:AbstractAutowireCapableBeanFactory这个类的中心方法:创建一个bean实例,填充bean实例,应用后处理器,等等

源码很长,就不截取了。在这里个方法里面,主要干了4件事情:

  1. 实例化(推断构造方法、实例化)
  2. BeanDefinition的后置处理
  3. 属性注入(实例化后、属性注入)(对的,你没看错,【实例化后】是在属性注入这个方法里面被调用的)
  4. 初始化

方法解读:正如方法注释说的,这里【创建一个bean实例,填充bean实例,应用后处理器】等等。这意味着,在这里包含了【实例化】过程中剩余的==【推断构造方法、实例化、BeanDefinition的后置处理、实例化后等】==步骤。另外,下一个章节会说的【IOC属性填充】、【IOC-Aware回调】、【IOC初始化】等阶段入口其实也是在这个方法中

*2.8 AbstractAutowireCapableBeanFactory#createBeanInstance:实例化

方法调用链:由2.7的doCreateBean调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
方法注释:AbstractAutowireCapableBeanFactory这个类的中心方法:创建一个bean实例,填充bean实例,应用后处理器,等等

源码如下:

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

方法解读:这里在实例化Bean的时候,采用了多种方式。如:

2.8.1 Supplier创建对象

Supplier,直译:供应商。
首先判断BeanDefinition中是否设置了Supplier,如果设置了则调用Supplier的get()得到对象。得直接使用BeanDefinition对象来设置Supplier,比如:

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

2.8.2 工厂方法创建对象

如果没有设置Supplier,则检查BeanDefinition中是否设置了factoryMethod,也就是工厂方法,有两种方式可以设置factoryMethod,比如:
方式一:

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

对应的UserService类为:

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

方式二:

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

对应的CommonService的类为:

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

Spring发现当前BeanDefinition方法设置了工厂方法后,就会区分这两种方式,然后调用工厂方法得到对象。
值得注意的是,我们通过@Bean所定义的BeanDefinition,是存在factoryMethod和factoryBean的,也就是和上面的方式二非常类似,@Bean所注解的方法就是factoryMethod,AppConfig对象就是factoryBean。如果@Bean所所注解的方法是static的,那么对应的就是方式一。

2.8.3 构造方法创建对象

RT。

2.9 AbstractAutowireCapableBeanFactory#autowireConstructor:推断构造方法

方法调用链:由2.7的createBeanInstance调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor
方法注释:推断构造方法,并且创建对象。

代码好长,我就不截取了。这里的代码看不看都还好,主要还是理解流程跟原则就好。

  1. 如果一个类只有一个构造方法,不管这个构造方法是有参还是无参,Spring都会使用这个构造方法创建对象
  2. 如果有多个构造方法,则看有没有无参构造方法。因为无参构造方法有默认的含义,若有,则选择无参的构造方法创建对象;
  3. 如果有多个构造方法,且没有无参,则看构造方法上是否有@Autowired注解,有就选择,没有就报错

额外的,在推断构造方法逻辑中除开会去选择构造方法以及查找入参对象意外,会还判断是否在对应的类中是否存在使用**@Lookup注解**了方法。如果存在则把该方法封装为LookupOverride对象并添加到BeanDefinition中。

在实例化时,如果判断出来当前BeanDefinition中没有LookupOverride,那就直接用构造方法反射得到一个实例对象。如果存在LookupOverride对象,也就是类中存在@Lookup注解了的方法,那就会生成一个代理对象。
@Lookup注解就是方法注入,使用demo如下:

@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后置处理

方法调用链:由2.7的doCreateBean调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
方法注释:将MergedBeanDefinitionPostProcessors应用于指定的bean定义,调用它们的postProcessMergedBeanDefinition方法。

源码如下:

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

方法解读:Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点,即当前的MergedBeanDefinitionPostProcessors。这里的主要难点还是,这种类型的BeanPostProcessor的应用场景,可能才是大家比较关心的。那你们觉得,这里的主要应用场景应该是什么呢?其实,按照Spring的生命周期来说,他现在提供给你的拓展点,只能是【实例化】阶段后的生命周期了,毕竟过去已经发生的已经没办法改变。所以,我们可以在这里,干预【初始化】这个阶段,如下示例:

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 {@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (beanName.equals("user")) {beanDefinition.setInitMethodName("myInit");}}
}

PS:在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache),为依赖注入做准备。

2.11 AbstractAutowireCapableBeanFactory#populateBean:属性注入(包含:实例化后)

(PS:属性注入不是我们这里需要关注的地方,但因为【实例化后】在这个方法里面,所以就只能点进来了)

方法调用链:由2.7的doCreateBean调用过来
全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
方法注释:使用来自bean定义的属性值在给定的BeanWrapper中填充bean实例(属性填充/依赖注入)。

populateBean中关键源码如下:

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

方法解读:在处理完BeanDefinition后,Spring又设计了一个扩展点:InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation(),比如:

@Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)) {UserService userService = (UserService) bean;userService.test();}return true;}
}

上述代码就是对userService所实例化出来的对象进行处理。这个扩展点,在Spring源码中基本没有怎么使用。估计是为了后面拓展做准备

方法总结后

以后可能不这么写了,挺麻烦的。我这样圈关键方法跟链路的原因,纯粹是想加深自己的印象,我也不知道放出来给大伙看,你们能否学习到什么。

三、实例化逻辑流程图

在这里插入图片描述

学习总结

  1. 学习了实例化的过程
  2. 学习了实例化过程中用到的2种【Bean后置处理器】:InstantiationAwareBeanPostProcessorMergedBeanDefinitionPostProcessor以及他们内部的一些方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/67779.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

USB协议精读

1.1.枚举 1.1.1.上电连接过程 1.1.2.设备识别过程 1.1.3.枚举过程 1.1.3.1.获取设备描述符&#xff08;只关注设备描述符中最大数据包长度&#xff09; 1.1.3.2.设置设备针对主机的唯一从机地址 1.1.3.3.获取完整设备描述符 1.1.3.4.获取配置描述符 先获取标准配置描述符&a…

【数据库基础】Mysql下载安装及配置

下载 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 当前最新版本为 8.0版本&#xff0c;可以在Product Version中选择指定版本&#xff0c;在Operating System中选择安装平台&#xff0c;如下 安装 MySQL安装文件分两种 .msi和.zip [外链图片转存失…

JVM运行时五大数据区域详解

前言&#xff1a; java虚拟机再执行Java程序的时候把它所拥有的内存区域划分了若干个数据区域。这些区域有着不同的功能&#xff0c;各司其职。这些区域不但功能不同&#xff0c;创建、销毁时间也不同。有些区域为线程私有&#xff0c;如&#xff1a;每个线程都有自己的程序计数…

openGauss学习笔记-39 openGauss 高级数据管理-分区表

文章目录 openGauss学习笔记-39 openGauss 高级数据管理-分区表39.1 范围分区表的分类39.2 创建范围分区39.2.1 创建VALUES LESS THAN范围分区表语法格式39.2.2 创建VALUES LESS THAN范围分区表参数说明39.2.3 创建VALUES LESS THAN范围分区表示例 39.3 询分区表39.3.1 查询分区…

【JPCS出版】第五届能源、电力与电网国际学术会议(ICEPG 2023)

第五届能源、电力与电网国际学术会议&#xff08;ICEPG 2023&#xff09; 2023 5th International Conference on Energy, Power and Grid 最近几年&#xff0c;不少代表委员把目光投向能源电力领域&#xff0c;对促进新能源发电产业健康发展、电力绿色低碳发展&#xff0c;提…

基于Yolov5与LabelMe训练自己数据的图像分割完整流程

基于Yolov5与LabelMe训练自己数据的实例分割完整流程 1. Yolov5配置2. 创建labelme虚拟环境4. 接下来开始使用labelme绘制分割数据集4.1 json to txt4.2 划分数据集(可分可不分) 5. 训练 1. Yolov5配置 参照这边文章&#xff1a; https://blog.csdn.net/ruotianxia/article/de…

常见分辨率时序信息

分辨率列表 分辨率一:640x480(逐行) 分辨率二:800x600(逐行) 分辨率三:1024x768(逐行) 分辨率四:大名鼎鼎720P(逐行) 注:选择720P@30帧的,需拉长HOR TOTAL TIME 分辨率五:1280x800(逐行) 分辨率六:1280x960(逐行

Nginx网站服务(安装nginx、平滑升级nginx、nginx各种访问配置)

一、Nginx概述 1、什么是nginx&#xff1f; 稳定性高、系统资源消耗低、对HTTP并发连接的处理能力高&#xff08;单台物理器可支持30000-50000个并发请求&#xff09; NG并发连接能力有2个因素的影响 ①CPU的个数 ②本地吴立琪系统的最大文件打开数2、Nginx应用场景 静态服…

学习笔记整理-JS-04-流程控制语句

文章目录 一、条件语句1. if语句的基本使用2. if else if多条件分支3. if语句算法题4. switch语句5. 三元运算符 二、循环语句1. for循环语句2. for循环算法题3. while循环语句4. break和continue5. do while语句 三、初识算法1. 什么是算法2. 累加器和累乘器3. 穷举法4. 综合算…

uni-app中使用pinia

目录 Pinia 是什么&#xff1f; uni-app 使用Pinia main.js 中引用pinia 创建和注册模块 定义pinia方式 选项options方式 定义pinia 页面中使用 pinia选项options方式 函数方式 定义pinia 页面中使用 函数方式 定义的pinia Pinia 是什么&#xff1f; Pinia&#xff0…

软件测试基础篇——MySQL

MySQL 1、数据库技术概述 数据库database&#xff1a;存放和管理各种数据的仓库&#xff0c;操作的对象主要是【数据data】&#xff0c;科学的组织和存储数据&#xff0c;高效的获取和处理数据SQL&#xff1a;结构化查询语言&#xff0c;专为**关系型数据库而建立的操作语言&…

Leetcode每日一题:833. 字符串中的查找与替换(2023.8.15 C++)

目录 833. 字符串中的查找与替换 题目描述&#xff1a; 实现代码与思路&#xff1a; 哈希表 模拟 原理思路&#xff1a; 833. 字符串中的查找与替换 题目描述&#xff1a; 你会得到一个字符串 s (索引从 0 开始)&#xff0c;你必须对它执行 k 个替换操作。替换操作以三个…