简述
这篇文章参照spring源码来了解一下bean的创建过程,本文的内容我在学习时画了一张图流程图,结合图和源码会比较直观
BeanFactory
bean工厂,一个创建bean的地方,他的主要方法是getBean
,如果已经生产过就直接返回,如果没有就生产后再返回
其中生产bean走得就是createBean
方法,也是本位主要要介绍的方法
同时为了可以支持个性化生产bean的过程,spring使用的bean工厂又支持添加bean后置处理器,并且多种类型,不同类型再bean生产的不同时期调用
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
用户通过添加后置处理器可以再某一个特定的生命周期参与bean的创建过程
createBean
这里开始跟踪createBean源码,分析重点操作的方法,首先有一句
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
这里先走了resolveBeforeInstantiation
,如果有返回直接返回bean,后续所有代码全部短路,那么就看一下resolveBeforeInstantiation
是干嘛
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// bean定义的beforeInstantiationResolved属性是true
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 如果有InstantiationAwareBeanPostProcessor类型的后置处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 执行这些后置处理器(InstantiationAwareBeanPostProcessor)
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 如果创建出bean,再执行BeanPostProcessorsAfterInitialization后置处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
总结就是这里开始执行InstantiationAwareBeanPostProcessor
类型的后置处理器postProcessBeforeInstantiation
方法,给用户一个机会使用它来完全自定义创建bean,最终如果创建出来了,只执行一个postProcessAfterInitialization
类型的后置处理器(这个后置处理器是实例化之后执行的,不管通过哪种方式,最终都会执行)就反回了。
看spring的注释是这么说的:Typically used to suppress default instantiation for specific target beans(通常用于抑制特定目标 bean 的默认实例化),也就是说用户如果有些特殊的bean不想按工程创建的套路生产,可以使用这种后置处理器来按自己的套路生产bean(这里我不知道spring有什么场景会使用它,以后再说)
doCreateBean
一般情况下,用户还是走工厂的套路去创建bean,所以当resolveBeforeInstantiation
返回null时,就开始按工厂的套路创建bean了,也就是doCreateBean方法
下面开始进入doCreateBean方法,还是只关注主干代码,下面的代码都是从源码贴出,只是贴重点
1.createBeanInstance
instanceWrapper = createBeanInstance(beanName, mbd, args);
这一步开始实例化bean,注意实例化和初始化的区别,简单实例化就是new,初始化就是执行一些初始化方法
这个方法也不用多说了,就是使用反射去创建对象(如果有构造方法注入这里还会更复杂,暂不讨论)
2.applyMergedBeanDefinitionPostProcessors
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
执行MergedBeanDefinitionPostProcessor类型的后置处理器,传出BeanDefinition,beanName,beanType,可以修改BeanDefinition或干点其他事
3.addSingletonFactory
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
添加三级缓存,对bean工厂三级缓存不懂得可以参考手写Spring之BeanFactory(三级缓存),这里添加的是一个工厂方法,如果方法被执行(出现循环依赖),会执行SmartInstantiationAwareBeanPostProcessor
后置处理器(主要是应付代理,后面介绍)
4.populateBean
populateBean(beanName, mbd, instanceWrapper);
给bean填充属性,这一步有很多重要子步骤
4.1 postProcessAfterInstantiation
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
这里也是执行InstantiationAwareBeanPostProcessor
的后置处理器,但与上面createBean
不同的是执行的是postProcessAfterInstantiation
方法,刚才那个postProcessBeforeInstantiation
返回的是object,如果有返回代表截断了bean的生产套路自己生产,而这个postProcessAfterInstantiation
方法如果返回false也是return
,短路了整个populateBean方法,也就是按照自己的套路填充属性(其实他俩的存在都是因为spring已经很多开放的后置处理器可以调整创建过程,但是不免会有些特殊情况,使用spring处理不来,name就可以使用这种短路的方式完全又用户自己掌控创建过程,就好像我们做一个文章编写的系统,给了各种title的输入框,并且可以选择,已经很灵活了,但是也不能覆盖所有用户需求,那就给你个选择,你可以按我们的套路编辑文章,也可以选择使用富文本,爱怎么写怎么写)
4.2 pvs
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
这里获取bean定义中指定的需要填充的属性,后续还可以加,最终一起填充
4.3 autowireByName | autowireByType
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
获取bean定义的依赖注入模式,然后调用autowireByName
或autowireByType
完成依赖注入
这种依赖注入是bean工厂提供的一种实现依赖注入的功能,但我们平时使用的注解形式依赖注入@Autowired
并不是使用这个功能,而是使用下面的4.4
这里如果有依赖注入的属性,并没有实际调用对象的set去赋值,而是存到pvs,还是最终一起填充
4.4 postProcessProperties
// 再次查找InstantiationAwareBeanPostProcessor类型后置处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 执行postProcessProperties方法
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
// 最终覆盖pvs(其实是添加)
pvs = pvsToUse;
}
}
还是执行InstantiationAwareBeanPostProcessor
后置处理器,执行postProcessProperties
,用户可以自定义要填充的属性,并填充到pvs,@Autowired
形式的注入就是写了一个这个后置处理器来实现的,一会单独说
4.5 applyPropertyValues
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
如果pvs(要填充的属性)不为空,执行填充(通过反射去set属性值)
这里总结一下pvs数据的来源: 1.bean定义里自带的(4.2) 2.通过bean定义的resolvedAutowireMode
去autowire的(4.3) 3.通过后置处理器返回的(4.4)
5.initializeBean
exposedObject = initializeBean(beanName, exposedObject, mbd);
初始化bean,也就是执行初始化方法什么的,进去看看
5.1 invokeAwareMethods
invokeAwareMethods(beanName, bean);
执行aware方法,这个aware翻译成中文就是感知,其实他的作用也挺简单,就是有的bean用户想让产品用有工厂的联系方式(beanFactory的引用),bean在工厂中的名字(BeanName),类加载器(BeanClassLoader),只要你的bean继承了对应的Aware接口,就会给你提供这些信息,比如继承了BeanFactoryAware
,再invokeAwareMethods
时就会执行setBeanFactory
方法并把BeanFactory传出来,至于bean爱保存还是拿着干什么随意。
有三种aware:
- BeanNameAware 可以获取到BeanName
- BeanClassLoaderAware 可以获取到BeanClassLoader
- BeanFactoryAware 可以获取到BeanFactory
5.2 applyBeanPostProcessorsBeforeInitialization
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
执行所有后置处理器的postProcessBeforeInitialization
方法,这一步可以获取到这个阶段的bean(wrappedBean里包含,初始化前),并可以返回一个新的bean覆盖原来的bean,比如创建代理
5.3 invokeInitMethods
执行初始化方法,也就是@PostConstruct注解的方法
5.4 applyBeanPostProcessorsAfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
执行所有后置处理器的postProcessBeforeInitialization
方法,这一步可以获取到这个阶段的bean(wrappedBean里包含,初始化后),并可以返回一个新的bean覆盖原来的bean,比如创建代理,spring的AOP实现就是再这里加了后置处理用代理bean覆盖了原bean
6.getSingleton
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
这一步主要看看有没有提前暴露,如果有则替换当前的bean,主要解决循环依赖和AOP,一会将循环依赖细说
7.registerDisposableBeanIfNecessary
registerDisposableBeanIfNecessary(beanName, bean, mbd);
这步记录bean,以便销毁时使用
到此整个创建过程就结束了,这是beanFactory创建bean的整个过程,并预留了很多钩子(后置处理器)可以实现各种特殊要求,spring的依赖注入和AOP就是通过添加后置处理器来实现的,流程图
@Autowired(AutowiredAnnotationBeanPostProcessor)
我们平时要实现依赖注入最常用的就是@Autowired
,意思要填充属性
通过对bean创建过程代码的分析并没有依靠@Autowired
填充属性的代码,但是有通过后置处理器填充属性的逻辑,不错,@Autowired就是依靠一个特定的后置处理器完成属性填充的。
这个后置处理器就是AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor
继承了MergedBeanDefinitionPostProcessor
和InstantiationAwareBeanPostProcessor
(其它的先忽略)
看看分别的实现,做了什么
postProcessMergedBeanDefinition
这个方法是在实例化之后调用
image.png
看看该后置处理器的实现
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
就不细说了,总结就是扫描bean的@Autowired和@Value注解,并通过beanName缓存起来
postProcessProperties
这个实在填充属性时调用
image.png
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
metadata.inject(bean, beanName, pvs);
return pvs;
}
代码就是获取上一步的缓存,然后给bean设置属性(我记得这一步是直接给bean就设置属性了,pvs并没有变,但我觉得应该先设置pvs,最后统一在applyPropertyValues的时候实际填充属性,这个可以自己看代码去确定)
总之,通过这两步,1.扫描@Autowired存缓存 2.根据缓存依赖注入 就完成了@Autowired
的功能
@AOP(AbstractAutoProxyCreator)
AOP功能实现的方式同样也是使用后置处理器,即AbstractAutoProxyCreator
,是一个抽象类,但主要的方法都在这里,所以就介绍他
主要实现了SmartInstantiationAwareBeanPostProcessor
和BeanPostProcessor
(其它先忽略)
看看分别的实现,做了什么
getEarlyBeanReference
这一步调用是出现循环依赖时调用
image.png
看看实现
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
// 根据beanName和class生成一个key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 使用key存储bean
this.earlyProxyReferences.put(cacheKey, bean);
// wrapIfNecessary
return wrapIfNecessary(bean, beanName, cacheKey);
}
主要是按特定的key存了一个缓存,然后执行wrapIfNecessary(其实就是如果设置了代理则创建代理)
如果这一步创建了代理,容器中就已经存放了当前bean的代理,所以bean的创建过程最后如果getSingleton
获取到了bean代表提前暴露了,创建了代理所以最终需要返回这个代理的bean对象,也就是
exposedObject = earlySingletonReference;
postProcessAfterInitialization
初始化结束之后执行
image.png
实现
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
这里的逻辑是之前走没走getEarlyBeanReference
(即有没有提前暴露),如果没走,执行wrapIfNecessary
,这里不懂的可以看看手写Spring之BeanFactory(三级缓存)这篇文章
wrapIfNecessary
两个方法都有用到wrapIfNecessary
,里面的代码就不贴了,最重要的是一句
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
即是创建代理,里面的内容就是创建代理的过程,可以参照我之前的Spring AOP系列文章
最后
spring支持注解依赖注入和AOP,但beanFactory本身不能实现这些功能,而是通过后置处理器方式实现的,那是谁把这些后置处理器交给BeanFactory的呐?答案就是ApplicationContext
over~
网友评论