springcloud原理_Spring的Bean实例化原理,这⼀次彻底搞懂
了
推荐学习
肝了⼗天半⽉,献上纯⼿绘“Spring/Cloud/Boot/MVC”全家桶脑图
微服务架构秘籍:SpringCloud+SpringCloud Alibaba,全⽹疯传
Aliyun四⾯真可怕,狂问基础+项⽬+源码+⾼阶,⽆爱了
前⾔
之前分析了Spring XML和注解的解析原理,并将其封装为BeanDefinition对象存放到IOC容器中,⽽这些只是refresh⽅法中的其中⼀个
步骤——obtainFreshBeanFactory,接下来就将围绕这这些BeanDefinition对象进⾏⼀系列的处理,如
BeanDefinitionRegistryPostProcessor对象⽅法的调⽤、BeanFactoryPostProcessor对象⽅法的调⽤以及Bean实例的创建都离不开
这些BeanDefinition对象。下⾯就来看看Spring是如何处理这些对象的。
正⽂
环境准备
⾸先我们先回忆下refresh⽅法:
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//为容器初始化做准备prepareRefresh();// 解析xm
prepareBeanFactory和postProcessBeanFactory没什么复杂的,关注⼀下⾥⾯设置了哪些值,添加了哪些对象就⾏,这些东西在后⾯
的流程中会起到作⽤。尤其是postProcessBeanFactory,这是⼀个模板⽅法,在其⼦类AbstractRefreshableWebApplicationContext
中设置了两个重要的标识:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 主要看着⾥⾯beanFactory.addBeanPostProcessor(new ServletContex
分别将hasInstantiationAwareBeanPostProcessors、hasDestructionAwareBeanPostProcessors属性都设置成了true,可以猜⼀下
它们有什么作⽤。
两个重要的Processor
在将上下⽂环境设置完成后,就是通过invokeBeanFactoryPostProcessors⽅法完成对BeanDefinitionRegistry以及BeanFactory的后
置处理器的处理和调⽤,也就是依次调⽤BeanDefinitionRegistryPostProcessor接⼝和BeanFactoryPostProcessor接⼝的实现类。我
们可以通过实现这两个接⼝在在BeanDefinition注册完成后,对象实例化之前对容器中的BeanDefinition进⾏动态的增删查改,⽐如
Spring中@Configuration注解的解析就是在这个过程中实现的。我们先来了解⼀下Spring内置的Processor实现有哪些:
整个体系需要有个⼤概的印象,其中重点关注ConfigurationClassPostProcessor类,该类就是完成对@Configuration、@Bean等注解
的解析注册,这⼀块的源码这⾥暂时不分析。继续开始的流程,进⼊到invokeBeanFactoryPostProcessors⽅法:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// getBeanFactoryPostProcessors⽅法⼀般是获取不到值的,除
这⾥⾯ 通过委托模式调⽤PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors⽅法,并传⼊了BeanFactory
和Processors对象,但需要注意getBeanFactoryPostProcessors⽅法不是获取通过xml配置和Component注解注册到容器中的
Processor对象,⽽是获取通过调⽤AbstractApplicationContext.addBeanFactoryPostProcessor⽅法添加的类,换⾔之我们实现了Processor接⼝后可以不在类上添加@Component,直接调⽤addBeanFactoryPostProcessor⽅法即可,但需要注意,这种⽅式并没有spring ioc注解
对应的BeanDefinition类,添加的对象也不存在于IOC容器中。
继续进⼊invokeBeanFactoryPostProcessors⽅法:
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {// Invoke BeanDefi
这个⽅法很长,但逻辑并不复杂。⾸先判断传⼊的BeanFactory对象是不是BeanDefinitionRegistry对象,是的话则优先调⽤传⼊的
Processor对象的postProcessBeanDefinitionRegistry⽅法,之后再通过BeanNamesForType拿到容器中所有BeanDefinitionRegistryPostProcessor实现类的名字,然后依次实例化并调⽤实现了PriorityOrdered、Ordered接⼝(前者优先级⾼于
后者,数字越⼩优先级越⾼)的Processor的postProcessBeanDefinitionRegistry⽅法,最后再实例化并调⽤剩余未实现排序接⼝的
Processor的⽅法。当所有BeanDefinitionRegistryPostProcessor实现类调⽤完成后,会依次调⽤来⾃于⽗接⼝
BeanFactoryPostProcessor的postProcessBeanFactory⽅法。
上述流程处理完成后,⼜会通过BeanNamesForType拿到容器中所有BeanFactoryPostProcessor实现类的名字,处
理流程和上⾯⼀样。
注册BeanPostProcessor对象
以上就是两个扩展点的调⽤流程,完成之后⼜会调⽤registerBeanPostProcessors注册所有BeanPostProcessor的⼦类到容器中来,这
个接⼝也是Spring的⼀个重要的扩展点,它包含了两个⽅法:
@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Nullabledefault Object po
实现了该接⼝的对象在实例化之前和之后分别会调⽤这两个⽅法。同样,我们先来了解下该接⼝的继承体系:
可以看到这个接⼝Spring内置的实现就⽐较多,可见⽤途之⼴泛。另外上⾯画红框的是本次需要重点记忆的类,后⾯Bean实例化时会出
现。接着我们来看看registerBeanPostProcessors的实现逻辑:
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {//拿到⼯程⾥⾯所有
这段代码的实现逻辑也很简单,也是先区分优先级,再获取Bean实例,最后注册到容器中,等到Bean实例化时调⽤。
接下来在refresh⽅法中调⽤了initMessageSource、initApplicationEventMulticaster、onRefresh、regi
sterListeners,分别是初始
化国际化资源、初始化时间⼴播器、容器刷新事件(⼦类回调)、注册,这⼏个⽅法都很简单,⾃⼰看看就⾏,这⾥就不详细阐述了。Bean对象的创建
当所有的准备⼯作都做好后,就该开始初始化Bean实例了,也就是finishBeanFactoryInitialization⽅法所做的事。不过这⾥可不是根据BeanDefinition new⼀个对象就完了,它包含了以下⼏个⼯作:
初始化实例
解析@PostConstruct,@PreDestroy,@Resource, @Autowired,@Value等注解
依赖注⼊
调⽤BeanPostProcessor⽅法
AOP⼊⼝(本篇暂不分析)
下⾯就来详细分析Bean实例化的整个流程:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {......//
重点看这个⽅法// Instantiate all remaining (non-lazy-init) single
在preInstantiateSingletons⽅法中可以看到这⾥有⼀个判断:单例、⾮懒加载、⾮抽象,满⾜这三个条件才会调⽤getBean(Bean实例化
都是通过调⽤该⽅法实现的)实例化:
public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}protected T doGetBean(final String name, @Nulla
这段代码⾸先从缓存⾥⾯拿到单例对象,如果没有,则通过scope类型去创建对应的Bean实例(直接创建或是通过
getObjectForBeanInstance调⽤FactoryBean接⼝的⽅法创建)。在创建对象之前如果scope是prototype类型的⾸先会通过isPrototypeCurrentlyInCreation检验是否存在循环依赖(循环依赖这⾥先不讲),存在直接抛出异常,原型对象不允许有循环依赖出现;校
验完成后还会通过DependsOn拿到@DependsOn注解的值,如果有,则会优先实例化依赖的对象。
因为⼤部分都是创建单例对象,所以下⾯我以getSingleton⽅法来分析,需要注意该⽅法传⼊了⼀个Lambda表达式,在该表达式中调⽤了createBean⽅法,观察其它scope创建bean会发现都调⽤了该⽅法,所以实际创建bean对象就是该⽅法,不过我们还是先进⼊
getSingleton⽅法看看做了些什么:
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {Null(beanName, "Bean name must not be null");synchronized (t
这个⽅法⾥⾯⾸先是从缓存中获取对象,如果有直接返回,如果没有则将该对象的beanName加⼊到singletonsCurrentlyInCreation缓存
中,如果添加不成功,说明已经有其它地⽅正在创建该对象,当前创建直接抛出异常,如果添加成功,则调⽤Object
去创建对象,这个⽅法就是传⼊的Lambda表达式,创建完成后删除掉singletonsCurrentlyInCreation缓存中的值并将对象添加到⼀级缓
存,后续需要该对象时,都是从⼀级缓存中获取的。
在getObject中通过createBean去创建对象,⽽该⽅法⼜调⽤了doCreateBean,我们直接来看这个⽅法:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Inst
这个⽅法⾥⾯⾸先去通过createBeanInstance创建对象的实例,创建完成后⼜通过applyMergedBeanDefinitionPostProcessors收集类
中的注解@Autowired、@Value、@PostConstruct,@PreDestroy,@Resource准备依赖注⼊或是⽅法调⽤,紧接着调⽤addSingletonFactory添加三级缓存处理循环依赖,之后通过populateBean依赖注⼊真正完成⼀个完整对象的创建,最后在initializeBean
中触发事件和⼀些⽅法的调⽤。下⾯逐个分析这些⽅法。
createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// Make sure bean class is actually res
在这个⽅法⾥⾯⼜做了很多判断,⾸先是拿到factoryMethodName,当我们在xml配置bean时指定了factory-bean属性和factory-
method属性或者是使⽤了@Bean注解时这⾥就会拿到值,然后就会通过FactoryMethod去创建⼀个实例对象;如果不存在factoryMethodName,那么就需要通过构造函数来实例化对象,但构造函数上可能存在注解@Autowired,因此需要通过determineConstructorsFromBeanPostProcessors获取到所有带@Autowired注解的构造函数:
protected Constructor>[] determineConstructorsFromBeanPostProcessors(@Nullable Class> beanClass, String beanName)throws BeansException {/** * 通过Auto
拿到所有带@Autowired注解的构造函数后就是通过调⽤autowireConstructor来进⾏实例化,具体则是通过委托给
ConstructorResolver类进⾏处理,包括上⾯通过factoryMethod创建对象也是委托给这个类。如果没有带@Autowired的构造函数才会
调⽤instantiateBean⽅法,利⽤反射通过⽆参构造函数去创建对象并返回,也是⼤部分对象实例化所⾛的流程。⾄此,简单对象的实例化
完成。
addSingletonFactory
这个⽅法就是添加三级缓存解决循环依赖问题,暂时不分析。
populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {boolean continueWithPropertyPopulation = true;//这⾥可
这⾥⾯主要有三个⽅法是完成依赖注⼊的:postProcessProperties(当前主要使⽤)、postProcessPropertyValues(⽼版本废弃API)、applyPropertyValues(xml中property标签)。所以主要看看postProcessProperties⽅法,⽽这个⽅法⼜是来⾃于InstantiationAwareBeanPostProcessor接⼝(希望你还记得这个接⼝的继承体系),主要看看
AutowiredAnnotationBeanPostProcessor,这个就是解决@Autowired依赖注⼊的。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findAutowiringMetadata
见名知意,findAutowiringMetadata⽅法就是拿到@Autowired注解的属性并封装为InjectionMetadata对象,再调⽤inject进⾏依赖注
⼊,注意这⾥是包含了属性和⽅法的(⽅法也不⼀定是setter⽅法才可以,只要是标记了@Autowired且参数类型正确都能依赖成功)。这就
是@Autowired的注⼊过程,另外还有@Resource的注⼊,在CommonAnnotationBeanPostProcessor类中,流程和这个基本⼀样,这
⾥就不阐述了。
initializeBean
以上过程都是对Bean的实例化,以及对象中属性的注⼊,都完成过后这个Bean对象才是我们真正可以直接使⽤的对象,所以接着就是处理
⼀些⽅法的调⽤了(包含⼀些事件通知)。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {if (SecurityManager() != null) {Ac
⾸先是Aware接⼝的⽅法调⽤,这个很简单不多说。接着就是applyBeanPostProcessorsBeforeInitialization⽅法调⽤,这个就是BeanPostProcessor接⼝的postProcessBeforeInitialization⽅法调⽤(看到这⾥你是否会发现⾃⼰之前理解错了呢,因为该⽅法是在对
象实例化之前调⽤,实际上也是实例化完成之后):
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;fo
这⾥⾯着重看⼏个实现类的调⽤:ApplicationContextAwareProcessor(ApplicationEventPublisherAware、
ApplicationContextAware等Aware接⼝的调⽤)、InitDestroyAnnotationBeanPostProcessor(@PostConstruct注解⽅法的调⽤)、ImportAwareBeanPostProcessor(ImportAware类型实例setImportMetadata调⽤,对理解SpringBoot帮助很⼤,这⾥可以暂时不
看)。
紧着着⼜通过invokeInitMethods⽅法调⽤InitializingBean接⼝的afterPropertiesSet⽅法以及init-method属性配置的⾃定义初始化⽅
法。
最后则是通过applyBeanPostProcessorsAfterInitialization⽅法调⽤BeanPostProcessor的postProcessAfterInitialization⽅法,因
为涉及到AOP知识,这⾥不详细分析。
⾄此,Bean的整个实例化过程分析完成,看到这⾥,你应该对于Bean的⽣命周期函数有个基本的认识了,最后放上我画的Bean实例化流
程时序图:
总结
本篇篇幅很长,中间很多⽆关痛痒的代码我都省略掉了,也有⼀些⽆关主流程但也⽐较重要的代码没有分析,⽐如ConfigurationClassPostProcessor解析@Configuration、@Bean注解的过程,FactoryMethod创建对象过程、获取@Autowired注解标记的构造函数以及通过这些构造函数实例化过程我都没有分析,⼀来是限于篇幅过长,⼆来主要是因为对理解整个流程并没有太⼤作⽤并且代码相对更简单,感兴趣的读者可在理解清楚主流程后⾃⾏分析。
作者:夜勿语
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论