SpringBoot Bean实例化流程解析
作者:LBruse
前置工作
新建一个RestService,代码如下
package geek.springboot.application.service; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; /** * Rest Service * * @author Bruse */ @Slf4j @Service public class RestService { @PostConstruct public void init() { log.info("RestService init...."); } }
finishBeanFactoryInitialization
来到 AbstractApplicationContext
的 refresh()
方法,在该方法中调用了 finishBeanFactoryInitialization()
方法
判断是否存在conversionService
首先判断当前IOC容器中是否存在 conversionService
,有的话将其设置到 BeanFactory
中
判断是否已有BeanFactoryPostProcessor
接下来判断当前 BeanFactory
中是否存在 BeanFactoryPostProcessor
,没有的话注册一个默认的实现
初始化LoadTimeWeaverAware
接着查询当前IOC容器中是否存在 LoadTimeWeaverAware
的实现,有的话则进行初始化。该类是使用AOP时做织入的一个工具类,一般情况下开发不会使用到它,所以这里其实并不会执行到循环体中的 getBean()
停止使用TempClassLoader
接下来将 BeanFactory
的 tempClassLoader
属性设置为null
调用freezeConfiguration()
接下来调用 freezeConfiguration()
方法,该方法主要是做一个 冻结
声明,即声明在此期间无法再向 BeanFactory
注册新的Bean定义
调用preInstantiateSingletons()
最后也是最关键的,调用 preInstantiateSingletons()
方法进行Bean的实例化
实例化Bean
最终其实会调用到 DefaultListableBeanFactor
的 preInstantiateSingletons()
方法。
首先会获取当前所有Bean定义的名称,并进行遍历
Tips:除了之前定义的service,controller,config...也包含了Spring内置的一些Bean
接着根据名称获取相关的 BeanDefinition
,也就是Bean的定义,它包括了Bean的一些元信息,比如是否单例,是否延迟初始化,该Bean依赖项等。
Tips:这里为了避免混淆视听,我事先已经在debug断点处加上了触发条件,只有beanName是restService时,断点才生效。
可以看到Spring会先根据 BeanDefinition
判断出当前类是否 抽象类
,是否 单例
,是否 延迟加载
。只有当当前 BeanDefinition
满足既不是 抽象类
,也不 延迟加载
的 单例
时,才会进行操作。
接着还会判断当前 Bean
是否实现了 FactoryBean
的接口,是的话则还要对 Bean
做一些处理。
因为之前创建的 RestService
没有实现 FactoryBean
接口,所以直接调用 getBean
方法
doGetBean
接着走到 AbstractBeanFactory
的 doGetBean()
方法,该方法主要作用就是返回一个指定的Bean实例
transformedBeanName
首先是对 Bean
的名称做一个处理,其中包含了若 BeanName
中包含了 FACTORY_BEAN_PREFIX
的话,则将其从 BeanName
中删除的逻辑
同时如果有设置 别名
的话,也会获取真正的 BeanName
再返回
getSingleton
接着进入 DefaultSingletonBeanRegistry
的 getSingleton
方法,该方法主要作用是 返回给定名称注册的单例对象
虽然这里逻辑很长,还用到了 双检锁
机制,但是其实从 singletonObjects
中检查是否有对应 beanName
的 Bean
存在时,因为是第一次创建,所以 singletonObjects
中并不存在相关的 Bean
,直接没进 if
方法体,就返回 null
了
isPrototypeCurrentlyInCreation
接着执行 AbstractBeanFactory
的 isPrototypeCurrentlyInCreation
方法,该方法主要是检查该 beanName
相关的 Bean
是否在当前线程创建中,因为我们这里还没有进行创建,所以这里方法返回false。
获取BeanFactory
接着尝试获取父类 BeanFactory
,并调用父类 BeanFactory
的 getBean
方法获取 Bean
,但是因为当前的 beanFactory
已经是最顶级的了,所以直接跳过大段代码。
Tips:Spring中BeanFactory跟JVM实现双亲委派机制的ClassLoader一样,也存在子级父级关系
markBeanAsCreated
接着执行 markBeanAsCreated
方法,这里也用到了 双检锁
机制,方法很简单,就是将 beanName
添加到 alreadyCreated
当中,算是做一个标识,标识当前 beanName
对应的 Bean
正在创建当中。
getMergedLocalBeanDefinition
接着调用 getMergedLocalBeanDefinition
方法获取 BeanDefinition
,并检查是否是抽象类,是的话直接抛出异常
检查是否存在依赖
接着检查当前要实例化的 Bean
是否和别的Bean存在依赖关系,是的话得先把所依赖的 Bean
创建好,才能继续实例化当前的 Bean
。
因为 RestService
中没有依赖什么别的 Bean
,所以这里略过一段代码
根据作用域创建Bean
接着便是根据作用域的不同,使用不同方式创建 Bean
getSingleton
这里进入 DefaultSingletonBeanRegistry
的 getSingleton
方法
这里首先还是会检查当前 Bean
是否已初始化,是的话直接返回
createBean
接着调用 ObjectFactory
的 getObject
方法,因为传参时是传递了一个 匿名内部类
,所以重新回到 AbstractBeanFactory
,可以看到调用了 createBean
方法
resolveBeanClass
接着来到 AbstractAutowireCapableBeanFactory
的 createBean
方法,首先会调用 AbstractBeanFactory
的 resolveBeanClass
方法对 BeanDefinition
对应的 Class
做一个解析,这里因为之前已经过了,所以直接返回。
resolveBeforeInstantiation
接着来到 resolveBeforeInstantiation
方法,可以看到如果它返回的 Bean
不为空,那么将直接返回,意味着 Bean
实例化完成。
接着深入查看具体实现细节,可以看到会判断当前IOC容器是否存在 InstantiationAwareBeanPostProcessor
接口的实现
如果存在 InstantiationAwareBeanPostProcessor
接口实现,则会调用其 postProcessBeforeInstantiation
方法,如果该方法返回值不为空,那么直接返回,并且调用 postProcessAfterInitialization
方法再对返回值做一些处理
因为当前项目中并没有存在 InstantiationAwareBeanPostProcessor
接口实现,所以直接返回的是 null
doCreateBean
所以初始化 Bean
的重任还是交给了 doCreateBean
方法
首先判断当前 Bean
是否单例,是的话将其从 factoryBeanInstanceCache
中移除
createBeanInstance
接着进入 createBeanInstance
方法,首先调用 getInstanceSupplier
方法判断当前 BeanDefinition
是否从其它配置加载的,然后调用 getFactoryMethodName
方法判断当前 BeanDefinition
是否存在工厂方法, RestService
两个条件都不满足,所以会一路执行到后续代码。
determineConstructorsFromBeanPostProcessors
接着执行到 determineConstructorsFromBeanPostProcessors
方法,该方法主要是 确定使用哪个构造器来初始化Bean
可以看到内部实现其实是依靠调用 SmartInstantiationAwareBeanPostProcessor
的 determineCandidateConstructors
方法来进行确定的
但其实最后返回的是 null
instantiateBean
最后来到 instantiateBean
方法,由注释也可以看出,该方法就是在 Bean
无需做特殊处理,调用默认无参构造函数即可初始化时调用的。
首先调用 getInstantiationStrategy
方法获取 实例化策略
,可以看到默认 实例化策略
是 CglibSubclassingInstantiationStrategy
instantiate
接着调用 instantiate
方法,在该方法中利用反射机制获取 类默认构造函数
BeanUtils.instantiateClass
最后调用 BeanUtils
的 instantiateClass
方法进行构建,可以看出其实该方法内部就是用了Java的 反射机制
进行类的实例构建
BeanWrapper
Bean
实例成功创建后,会创建 BeanWrapper
实例来对 Bean
实例做一个包装,并调用 initBeanWrapper
方法对 BeanWrapper
进行初始化操作
可以看到最后返回的不是 BeanInstance
,而是把 BeanInstance
给包裹了一层,返回的 BeanWrapper
。
applyMergedBeanDefinitionPostProcessors
接着调用 applyMergedBeanDefinitionPostProcessors
方法,该方法本质即获取所有 MergedBeanDefinitionPostProcessor
实现,并逐个调用其 postProcessMergedBeanDefinition
方法
populateBean
接着执行 populateBean
方法,该方法主要用来填充当前的 BeanInstance
会获取当前 BeanDefinition
的所有 Property
,并判断以何种方式进行自动注入,根据类型?根据名称?
还可以看到会尝试获取所有 InstantiationAwareBeanPostProcessor
实现,并调用其 postProcessProperties
方法
总结
在Spring实例化Bean的过程中, BeanDefinition
几乎贯穿了整个流程,而 BeanDefinition
是一个对象在Spring中的描述,Spring通过操作 BeanDefinition
来完成 Bean
的实例化和属性注入,而实例化的过程中又使用到了Java中非常基础且重要的—— 反射
以上就是SpringBoot Bean实例化流程解析的详细内容,更多关于SpringBoot Bean实例化的资料请关注脚本之家其它相关文章!