一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
Spring 源码阅读笔记(八)
前篇导航
Spring 源码阅读笔记(一)
Spring 源码阅读笔记(二)
Spring 源码阅读笔记(三)
Spring 源码阅读笔记(四)
Spring 源码阅读笔记(五)
Spring 源码阅读笔记(六) 主线 registerBeanPostProcessors解读
Spring 源码阅读笔记(七) 支线 getBean方法解读
前篇回顾
在上一章节中,把getBean方法的整个流程走了一遍,可以得到一个信息,调用AbstractBeanFactory的getBean方法时,如果工厂中找不到类的话,不会返回空,而是会调用CreateBean方法。那么这篇文章解读的就是createBean方法。
正式开始
关于CreateBean,这个方法具体的实现代码位于AbstractAutowrieCapableBeanFactory中。首先先关注一下这个方法的入参。
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args);
- String beanName 要创建的Bean名称
- RootBeanDefinition mbd 要创建的Bean的定义信息
- Object[] args 不出意外这里传空
首先呢,读方法之前,粗略的看一下重点,在哪里,哪些细节要抠。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 确保此时实际解析了 bean 类,
// 并克隆 bean 定义以防动态解析的 Class
// 无法存储在共享的合并 bean 定义中。
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
// 准备方法覆盖。
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
// .....
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 让 BeanPostProcessors 有机会返回一个代理而不是目标 bean 实例。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
// ...
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// ....
}
catch (Throwable ex) {
// ....
}
}
上方的代码粗略看一眼,完成了以下的几个点。
- 新创建了一个BeanDefinition对象
- 解析上层传过来BeanDefintion,解析出Class信息,赋值给了新的BeanDefinition
- 调用resolveBeforeInstantiation,注释解释让BeanPostProcessors有机会返回代理,而不是目标bean实例。
- Object beanInstance = doCreateBean(beanName, mbdToUse, args);
从这里基本都可以看出,具体关键性的代码是resolveBeforeInstantiation方法和doCreateBean。
resolveBeforeInstantiation
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.
// 确保bean类在这一点上得到了解决。
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// .....
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
该方法一进入便可看到一个判断,beforeInstantiationResolved这个值是做什么的,要看一下他的注释。解释如下
- Package-visible field that indicates a before-instantiation post-processor having kicked in.
- Package visible字段,指示前实例化后处理器已启动。
讲真话,我看不懂是什么意思😂,知道这里是null值就行,因为我们并没有设置他的值。
那么这里false.equals(null) = false 在加上一个取反,很明显if进来了。
接下来进入第二个if判断,BeanDefinition中的synthetic属性为boolean类型,默认为false,他这里取反了一下,这个条件也成立,但是看到他有个&&,这里要去看一下他的代码。
protected boolean hasInstantiationAwareBeanPostProcessors() {
return !getBeanPostProcessorCache().instantiationAware.isEmpty();
}
class AbstractBeanFactory:
BeanPostProcessorCache getBeanPostProcessorCache() {
BeanPostProcessorCache bppCache = this.beanPostProcessorCache;
if (bppCache == null) {
bppCache = new BeanPostProcessorCache();
for (BeanPostProcessor bpp : this.beanPostProcessors) {
if (bpp instanceof InstantiationAwareBeanPostProcessor instantiationAwareBpp) {
bppCache.instantiationAware.add(instantiationAwareBpp);
if (bpp instanceof SmartInstantiationAwareBeanPostProcessor smartInstantiationAwareBpp) {
bppCache.smartInstantiationAware.add(smartInstantiationAwareBpp);
}
}
if (bpp instanceof DestructionAwareBeanPostProcessor destructionAwareBpp) {
bppCache.destructionAware.add(destructionAwareBpp);
}
if (bpp instanceof MergedBeanDefinitionPostProcessor mergedBeanDefBpp) {
bppCache.mergedDefinition.add(mergedBeanDefBpp);
}
}
this.beanPostProcessorCache = bppCache;
}
return bppCache;
}
看到这里有点懵了,方法的含义是获取Bean后处理的缓存。然后这个beanPostProcessorCache属性我不记得什么时候设置过了,这里打个断点看一下吧。
这里有个应用事件监听器,我有点印象,虽然不知道是干嘛的,我印象中他是在invokeBeanFactoryPostProcessors方法时创建的。那么由此也得知了hasInstantiationAwareBeanPostProcessors方法返回为False,后面的代码块也就不执行了。 这个方法返回的是null值。
后续进入doCreateBean方法。
doCreateBean方法
doCreateBean 入参
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
这个方法一共只有三个入参,很透明。
- beanName 需要创建的Bean的名称
- BeanDefintiton Bean定义信息,在上一步已经把ClassName转换成BeanClass
- args 从getBean方法传过来的,不出意外的话,这个是为空。
后面由于这个方法体比较长,这里还是采用分段阅读方法,具体分段规则是根据源码中的注释来分段的。
doCreateBean 第一段代码
// Instantiate the bean.
// 实例化 bean。
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
接下来看第一段代码,根据代码上方的注释可以看到,实例化Bean,那么众所周知,创建一个对象要分几步,实例化,初始化。在实例化时只是创建了一个对象,这里粗略扫一眼可以看到几个比较关键的方法。
- createBeanInstance
- 返回一个BeanWrapper,根据字面意思就是Bean包装器,我还没有看里面的代码,我先简单理解成对Class的一个封装。
- getWrappedInstance
- 字面意思是获取包装器实例,现在没看代码,我的理解是通过Class,instance出来一个对象。
接下来看看这两个方法的代码具体如何实现
createBeanInstance
完整的createBeanInstance方法也蛮长的,这里分段吧,方便讲解。
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// .... 中间省略一些不会进入的if
// Shortcut when re-creating the same bean...
// 重新创建同一个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);
}
}
这里的方法很明显了,一进入第一行就是获取当前要创建Bean的Class。
后来进入一个If判断,args正常情况下势必为null。进入If。
不出意外的话,BeanDefinition中的resolvedConstructorOrFactoryMethod属性我们并没有设置过,所以为null,这里不会进入。由于这个if没有进入,所以resolved的值没有发生改变,那么下一个if也不会进入。
// Candidate constructors for autowiring?
// 自动装配的候选构造函数?
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);
}
这段代码粗略读下来,获取的类的构造方法,判断构造方法有没有自动注入,有的话,走使用构造方法构建实例的方法。
// No special handling: simply use no-arg constructor.
// 没有特殊处理:只需使用无参数构造函数。
return instantiateBean(beanName, mbd);
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
这里代码一层一层追下来,可以得知,他是通过反射来创建了一个实例。
然后把实例封装进了BeanWrapper类中,这个类是干什么的不重要,只要记住,可以通过这个对象拿到实例就可以了。
doCreateBean 第二段代码
// Allow post-processors to modify the merged bean definition.
// 允许后处理器修改合并的 bean 定义。
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw .....
}
mbd.postProcessed = true;
}
}
postProcessed默认值为false,由于我们没有进行过更改,所以这里会进入If。
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
这里扫一眼就行,没什么实质意义,系统定义了几个PostProcessor这里要执行一下。
随后mbd.postProcessed = true;设置的postProcessed状态,代表已经执行过了。
doCreateBean 第三段代码
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 急切地缓存单例以便能够解析循环引用
// 即使由生命周期接口(如 BeanFactoryAware)触发。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
方法一开始拿到了一个bool类型的值earlySingletonExposure,这里取了三个值。
- 是否单例
- 是否允许循环引用 默认为true
- 判断当前创建的Bean在整个工厂中是否正在创建,有点拗口。这里是为true的,因为我们现在正在创建的就是这个类。
然后后面就是添加了个,单例工厂,我猜测这个工厂的作用就是把刚刚上面实例化的Bean对象,给返回出去,来解决循环依赖问题。
doCreateBean 第四段代码
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw ......
}
}
这里可能比较疑惑,为什么要把Bean重新赋值,这里可以想一下,Bean是Object,也就是引用类型,那么在刚刚的代码中,有把Bean赋值给刚刚解决循环引用的地方,所以这里为了在那个方法被调用时Bean不发生改变,所以这里重新声明了一个对象。
后面为这个对象进行populate操作,也就是填充属性。
populateBean
populateBean 入参
- String beanName
- RootBeanDefinition mbd
- @Nullable BeanWrapper bw 封装着Bean的实例对象
populateBean 第一段代码
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
bw不为空,具体看入参
populateBean 第二段代码
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
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;
}
由于我们这个里面没有设置properties文件,所以pvs刚开始时是为null的。
第二个变量的自动装配模式,由于我们没有另外的设置,所以采用的是默认方式,也就是注解注入的方式,下面这里的if中,分别也byName或者byType,他们的所代表的也就是setter方法的注入方式。有兴趣可以去读一下,我这里就跳过了。因为我们在正常的开发中,通常是不设置这个的,都是通过注解注入。
initializeBean
initializeBean 第一段代码
invokeAwareMethods(beanName, bean);
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
在方法一开始执行了aware接口的方法。但是这里发现一个细节,并没有发现applicationAware接口。接着往下看。
initializeBean 第二段方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 执行BeanPostProcessor
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
从上方的代码可以看出来获取了所有的BeanPostProcessor,然后遍历一遍去执行他们的Before方法。
这里值得一提的是。ApplicationContextAwrea是在PostProcessor里面处理的。
initializeBean 第三段方法
try {
// 执行Bean的初始化方法,afterProperties方法也是在这里执行的。
// Xml中指定的init-methods。
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
这里就没有什么好读的了。调用了一下xml里面的init方法。
值得一提的是,InitializingBean接口中的afterPropertiesSet方法也是在这个时候被执行的。
initializeBean 第四段方法
if (mbd == null || !mbd.isSynthetic()) {
// 执行BeanProcessor的后置增强器。
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
这里就简单,和前面一样BeanPostProcess方法一样。只不过有befor方法换成了after方法。
doCreateBean 第五段代码
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw .....
}
}
}
}
由于上方的boolean对象没有变过,所以此时他还是为True。第一行代码获取了一个他的单例工厂中的对象。
由于allowEarlyReference是为false的。所以获取的对对象是个null,那么也就代表剩余的If不会进入。
doCreateBean 第六段代码
// Register bean as disposable.
// 将 bean 注册为一次性的。
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
后面直接放回了上面代码中经历了种种操作的Bean。至于registerDisposableBeanIfNecessary这个方法,没看懂他的实现,并且经过debug后,发现他里面的代码并没有执行,所以这里先跳过吧。
告一段落
这篇文章到这里就结束了,相信看完这篇文章后,如果面试时,对方问道Bean的创建流程时你就可以对答如流了。大家加油~
都看到这了,点个赞再走呗,宝~
结束语
写文章的目的是为了帮助自己巩固知识,写的不好或者错误的地方可以在评论区指出。如果您看了文章觉得对您有所帮助可以点个赞,如果发现有些问题产生了疑惑,或者不明白的可以评论、加我微信,一定知无不言。当然也希望和大家交个朋友,相互学习。