Spring boot启动流程-bean的实例化和初始化

AbstractApplicationContext类的refresh方法中,调用了finishBeanFactoryInitialization(beanFactory)方法,完成了bean factory的初始化,其中就包括bean的实例化和初始化。
本文仅关注单例bean的实例化和初始化流程中的关键步骤

实例化

finishBeanFactoryInitialization(beanFactory) -> beanFactory.preInstantiateSingletons

1、遍历bean factory中的bean name,根据bean name获取merged bean definition,类型为RootBeanDefinition,是bean factory运行时的统一bean definition视图。这里的merged,指如果当前bean definition是子bean definition,需要将它与父bean definition进行合并。

2、检查RootBeanDefinition是否满足:非抽象、单例、非懒初始化。满足后判断是否为factory bean,是则进入factory bean处理逻辑,否则进入getBean(beanName)方法。

getBean(beanName) -> doGetBean

3、调用getSingleton(beanName),检查缓存中已经实例化的单例,也可以对当前正在创建中的单例提供早期引用(解决循环依赖问题);如果拿到则直接使用,否则进入下一步。

4、获取当前bean factory的父工厂,如果满足:父工厂存在,且当前工厂中没有目标bean definition,则从父工厂中获取bean实例;否则进入下一步。

5、根据beanName获取当前的RootBeanDefinition对象,确保当前bean所依赖(depends On)的bean全部初始化完毕。

6、开始创建bean实例,判断是否是单例bean。如果不是,则进入非单例bean逻辑;如果是单例,则调用getSingleton的重载方法,其中一个参数是spring的ObjectFactory函数式接口的实现,这里使用lambda表达式,调用AbstractBeanFactory的子类AbstractAutowireCapableBeanFactory(具备自动装配能力的抽象bean工厂)的createBean方法来实现接口的getObject()功能

doGetBean -> createBean

7、准备方法重写,找到需要spring进行重写的方法(比如@Lookup注解方法),如果某个名字的方法只有一个,也就是说没有重载方法,那么在这里先标记为非重载,避免重写的时候产生检查是否重载的额外开销。

8、首先给所有InstantiationAwareBeanPostProcessor(实例化感知的BeanPostProcessor)一个机会,调用其postProcessBeforeInstantiation方法,来返回一个目标bean的代理对象。如果创建了代理对象,则返回;否则进入doCreateBean方法。

createBean -> doCreateBean -> createBeanInstance

9、获取当前bean definition中的instanceSupplier(实例供应商,实现了Supplier函数式接口)。如果存在则通过get方法获取bean实例;
否则获取当前bean definition的工厂方法,如果有则使用工厂方法实例化bean,
否则遍历SmartInstantiationAwareBeanPostProcessor,调用其determineCandidateConstructors方法获取候选构造方法(比如AutowiredAnnotationBeanPostProcessor会解析带@Autowired注解的构造方法),然后结合其他条件判断是否进行构造器自动注入(autowireConstructor方法,包括确定最终使用的构造器、解决参数的自动注入、通过构造器实例化bean等)。

判断是否调用autowireConstructor的条件:候选构造器不为空,或者bean definition的AutowireMode为AUTOWIRE_CONSTRUCTOR,或者bean definition中设置了构造器参数值,或者上游有传入参数。
如果以上方法都不可行,则从bean definition中获取指定的构造函数,如果没有,则使用默认的无参构造函数,进入instantiateBean方法。

createBeanInstance -> instantiateBean -> getInstantiationStrategy().instantiate

10、检查bean definition中是否有需要重写的方法(比如带@Lookup注解),有的话需要使用CGLIB动态代理生成子类对象将其实现;没有的话使用默认构造函数。

getInstantiationStrategy().instantiate -> BeanUtils.instantiateClass

11、instantiateClass中,最终使用反射,即Constructor类的newInstance方法完成bean的实例化。

BeanUtils.instantiateClass ----> instantiateBean ----> doCreateBean

12、返回到instantiateBean方法,构建并初始化BeanWrapper(对bean实例的一层包装),再返回到doCreateBean方法。

衔接实例化与初始化

1、doCreateBean方法中拿到bean实例后,遍历MergedBeanDefinitionPostProcessor,调用其postProcessMergedBeanDefinition方法,使其能够对RootBeanDefinition进行操作。
这里需要注意两个PostProcessor:
1)CommonAnnotationBeanPostProcessor,它做了两件事:

  • 解析bean的生命周期元数据(比如自定义的带@PostConstruct注解的初始化方法、带@PreDestroy注解的销毁方法等)并保存起来。
  • 解析@Resource注解,然后构建InjectionMetadata(注入元数据)保存起来。
    2)AutowiredAnnotationBeanPostProcessor,解析@Autowired和@Value注解,构建InjectionMetadata(注入元数据)保存起来。

2、如果项目允许循环依赖,尽早把单例缓存起来以解决循环依赖问题。当前版本spring boot已经默认关闭了循环依赖,可以通过配置文件设置开启。

初始化

doCreateBean -> populateBean

1、populateBean,填充属性。首先给所有的InstantiationAwareBeanPostProcessor一个机会,调用postProcessAfterInstantiation方法,对bean进行操作,比如添加自定义属性。

2、调用mbd.getResolvedAutowireMode方法,获取merged bean definition的自动装配模式,

  • 如果是AUTOWIRE_BY_NAME,则先通过java bean的内省机制,解析类中的getter/setter方法,得到属性名、属性类型、读方法、写方法等信息,组成若干PropertyDescriptor对象,然后根据其中的属性名进行自动注入,再将属性名和属性对象保存到当前bean definition的PropertyValues中。
  • 如果是AUTOWIRE_BY_TYPE,则同样先通过内省机制拿到PropertyDescriptor对象,然后根据属性的写方法的参数类型进行自动注入,再将属性名和参数对象保存到当前bean definition的PropertyValues中。

3、再次遍历InstantiationAwareBeanPostProcessor,调用其postProcessProperties方法注入依赖(可以是bean的属性,也可以是方法参数)。这里同样的:
CommonAnnotationBeanPostProcessor,拿到InjectionMetadata(之前有缓存,解析了@Resource注解),进行依赖注入。
AutowiredAnnotationBeanPostProcessor,拿到InjectionMetadata(之前有缓存,解析了@Autowired和@Value注解),进行依赖注入。

依赖注入的过程(以@Autowired和@Value为例)
获取InjectionMetadata里面的元素,调用element.inject方法开始属性注入,如果是属性元素,则:
1)如果当前的依赖关系有缓存,则从缓存中获取,没有则调用resolveFieldValue方法;

2)inject -> resolveFieldValue -> beanFactory.resolveDependency
这里对依赖的类型进行了多种特殊判断(Optional类型、ObjectFactory接口类型等),做出不同处理,同时为带有@Lazy注解的依赖,生成了一个代理对象。而对于我们常用的普通对象,调用doResolveDependency方法。

3)beanFactory.resolveDependency -> doResolveDependency
先找到当前依赖的@Value注解的建议值,如果有值则进行解析,必要时进行类型转换,然后返回到resolveFieldValue方法中。如果没有要处理的@Value注解,则进入下一步。

4)调用resolveMultipleBeans,处理多个bean,比如依赖的类型为数组类型、Connection集合类型、Map类型等,然后将结果返回到resolveFieldValue方法中。如果只是单对象依赖,直接进入下一步。

5)调用findAutowireCandidates,找到与依赖类型匹配的候选beanName及对应的Class对象(内部调用bean factory的getBeanNamesForType方法)。

6)调用descriptor.resolveCandidate(内部又调用beanFactory.getBean(beanName)方法),获取或者创建一个依赖bean实例。

7)返回到resolveFieldValue中,将依赖bean注册到bean factory的dependentBeanMap变量中;并将依赖关系保存在AutowiredAnnotationBeanPostProcessor的缓存中。

8)返回到inject方法,通过反射对当前bean的属性进行赋值。

如果是方法元素,则需要解决的是方法参数的自动注入,和属性依赖相似,调用beanFactory.resolveDependency方法,完成参数bean的实例化,然后注册、缓存依赖关系,最后通过反射调用该方法。

4、回到populateBean,调用applyPropertyValues方法,对PropertyValues中的属性,调用其写方法进行赋值。

doCreateBean -> initializeBean

5、invokeAwareMethods,调用感知方法,比如主类bean就是spring boot通过ConfigurationClassEnhancer生成的代理类对象,
实现了BeanFactoryAware接口,调用了setBeanFactory方法。

6、applyBeanPostProcessorsBeforeInitialization,遍历所有BeanPostProcessor,调用其postProcessBeforeInitialization方法,作用是在invokeInitMethods调用初始化方法之前进行BeanPostProcessor指定的初始化操作,
比如CommonAnnotationBeanPostProcessor的父类InitDestroyAnnotationBeanPostProcessor中,就会调用@PostConstruct注解的初始化方法。
又比如ConfigurationPropertiesBindingPostProcessor,会处理@ConfigurationProperties注解,我们在注入JDBCTemplete依赖的时候,将application.property文件中的spring.datasource相关的数据源配置与dataSourceProperties这个bean绑定,用来初始化JDBCTemplete。

7、invokeInitMethods,首先检查当前bean是否实现InitializingBean,如果是则执行其afterPropertiesSet方法;然后获取并调用bean definition中自定义的初始化方法。

8、applyBeanPostProcessorsAfterInitialization,遍历所有BeanPostProcessor,调用其postProcessAfterInitialization方法。此时initializeBean方法结束,返回到doCreateBean。

initializeBean -> doCreateBean

9、判断是否提前暴露。

10、registerDisposableBeanIfNecessary,注册DisposableBean。如果当前bean实现了DisposableBean接口,拥有自定义销毁方法,或者bean factory中注册了DestructionAwareBeanPostProcessors(销毁感知的BeanPostProcessor),则将该单例bean添加到disposableBeans变量中。
到此doCreateBean方法结束,返回初始化完成的bean实例,回到doGetBean的getSingleton重载方法。

doCreateBean -> doGetBean

11、getSingleton中拿到bean实例后,对bean factory的singletonsCurrentlyInCreation和singletonObjects等集合进行更新,然后返回bean实例。
12、调用getObjectForBeanInstance方法,根据bean实例获取最终的对象。主要处理流程:

  • 如果入参name包含factory bean的前缀字符’&',则返回该bean实例(如果发现不是factory bean会报错);
  • 未实现FactoryBean接口的普通bean,直接返回该bean实例;
  • 实现了FactoryBean接口的工厂bean,调用其getObject()方法生成最终对象(比如mybatis的mapper,就是工厂bean创建的代理对象)。

doGetBean -> getBean(beanName) -> preInstantiateSingletons -> finishBeanFactoryInitialization

bean的实例化和初始化结束。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值