1 吐槽
学spring,用spring,天天围绕着这么一个框架转;Autowired,Resource,Service,Controller,Repository,各种注解都写了不下千遍,敲代码得速度可能比菜市场的老大妈算菜钱的心算速度都要快了;樱花下落的速度是五厘米每秒,我敲注解的手速是1分钟30个。。。。。
然而代码敲了很多,始终停留在应用层面,而且是很粗浅的日常使用罢了,就像老大妈只知道一斤菠菜3.2块钱,3斤菠菜就是9.6块一样,虽心算速度直逼计算机,却不知这种程度的计算在整个数学的菜单里,就像一盘菜里的大蒜葱花一般,是基础,但是也就只是基础,不算一道完整菜。
于是,神(我自己)说,要有源码。
所以,就有了源码的学习。
(PS:本文的思路和内容都是源自于郝佳大佬写的《spring源码深度解析《(第2版)》一书,个人只是学习总结和记录,如果对源码有兴趣,可以买书支持一下!!!)
2 切入点
2.1 切入点
AbstractBeanFactory 中的 getBean() 方法。
一般在学spring的时候,比如学习spring过程中写的demo里,需要从容器中拿一个bean,经常出现对如下这个方法的使用,大致是这样的:
ApplicationContext app = new AnnotationConfigApplicationContext(xxxConfig.class);
app.getBean("一个bean");
看起来很普通的从new出来的spring容器中拿了一个bean而已,一个七个字母的方法,其实就内部的源码里就包含了对bean的加载过程。
跟进,其源码如下:
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
这里剧透一下,在日后窥探spring源码精髓的过程中,可能会发现一些规律,那就是一个真正的干活函数,往往是以do开头的,如 getBean 中的 doGetBean 方法;而这些表面上看起来在干活的函数,如 getBean,只做一些统筹全局的工作,并调用这些真正的干活函数。
跟进 doGetBean 方法:
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
//注释1-----------------------------------------------------------------------
String beanName = this.transformedBeanName(name);
//注释2-----------------------------------------------------------------------
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
if (this.logger.isDebugEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//注释3----------------------------------------------------------------------
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
//注释4----------------------------------------------------------------------
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//注释5----------------------------------------------------------------------
BeanFactory parentBeanFactory = this.getParentBeanFactory();
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
try {
//注释6----------------------------------------------------------------------
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
//注释7----------------------------------------------------------------------
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if (dependsOn != null) {
var11 = dependsOn;
int var12 = dependsOn.length;
for(int var13 = 0; var13 < var12; ++var13) {
String dep = var11[var13];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
this.registerDependentBean(dep, beanName);
try {
this.getBean(dep);
} catch (NoSuchBeanDefinitionException var24) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
}
}
}
//注释8----------------------------------------------------------------------
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
var11 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
//注释8----------------------------------------------------------------------
String scopeName = mbd.getScope();
Scope scope = (Scope)this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
this.beforePrototypeCreation(beanName);
Object var4;
try {
var4 = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
return var4;
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var23) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);
}
}
} catch (BeansException var26) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var26;
}
}
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
} else {
return convertedBean;
}
} catch (TypeMismatchException var25) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
} else {
return bean;
}
}
当场懵逼。这个方法怎么这么长?这些变量、参数都是谁?他们凑在一起在干嘛?我可以退出源码学习吗?
莫急,一一拆开来,先从大致流程来,看看spring都做了些啥。
2.2 这个方法做了什么?
1)转换对应的beanName (注释1处)
String beanName = this.transformedBeanName(name);
在我初步学习的时候,就曾对此表示疑问:我从外部传进来的不就是beanName吗?为何还要转换?
确实,一般来说是传进来的beanName,但是也有其他情况,比如别名,或者想要FactoryBean而不是其中的对象,此时传入的可不是我们常用的beanName了。
这里插一句,想要获得FactoryBean,是这样的,此时才能拿到装着bean的FactoryBean:
app.getBean("&bean")
2)尝试从缓存中加载单例 (注释2处)
Object sharedInstance = this.getSingleton(beanName);
如标题意思所述。
3)获取bean的实例 (注释3处)
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
从前几行的if语句中可以看出,缓存中是存在该bean的,但是spring缓存中记录的是bean的初始状态,并不一定是我们想要的最终的bean,spring需要对其再加工一下变成我们真正需要的bean,而 getObjectForBeanInstance 就是用来完成这一工作的函数;
4)对非单例bean的检查 (注释4处)
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
if 判断中的方法名为:isPrototypeCurrentlyInCreation,字面意思呢,就是正在创建中的多例bean;
具体什么意思?就是我们在 getBean 方法中传入的beanName所指向的那个bean,还在创建呢,而且是多例的,对于多例的bean,不会在容器启动时创建,其只有在被调用时才创建,所以此时不能拿。此时,spring也不知道该干嘛了,就报个错吧。
5)检测parentBeanFactory (注释5处)
BeanFactory parentBeanFactory = this.getParentBeanFactory();
//如果beanDefinitionMap中也就是在所有已经加载的类中不包括beanName,则尝试去父类工厂中检测
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
缓存中没有,配置里也没有所需的bean,就尝试去父类工厂里加载bean;
6)将配置中GenericBeanDefinition 转换为 RootBeanDefinition (注释6)
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
spring把从配置中拿到的bean信息存储在了 GenericBeanDefinition 中,但是doCreateBean这个方法中处理的是 RootBeanDefinition ,所以需要转换一下,同时若这个bean有父类,则顺带合并一哈。
7)寻找依赖 (注释7)
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if (dependsOn != null) {
var11 = dependsOn;
int var12 = dependsOn.length;
for(int var13 = 0; var13 < var12; ++var13) {
String dep = var11[var13];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
this.registerDependentBean(dep, beanName);
try {
this.getBean(dep);
} catch (NoSuchBeanDefinitionException var24) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
}
}
}
在bean初始化的时候,可能会用到一些属性,且这些属性的配置依赖于其他的bean,那么这时,需要先初始化bean所需的依赖。 注意是初始化。
8) 对不同的scope的bean进行创建 (注释8)
见代码。
3 详解:
3.1 从缓存中获取单例bean
3.1.1 尝试从缓存中获取
虽说是获取,但是也只是尝试获取,获取不到就算了。
这里提一句,spring为了避免循环依赖,会在bean还未创建完成时,便把创建bean时对应的ObecjtFactory曝光到缓存,以便其他需要该bean的对象引用;
获取单例bean时,先尝试从缓存中加载,如果失败,则再尝试从singletonFactories中加载ObecjtFactory
上代码:
//
@Nullable
public Object getSingleton(String beanName) {
return this.getSingleton(beanName, true); //true 为allowEarlyReference
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
这段代码里,怎么这么多xxxxxxObjects? 看的头疼。
这里面出现的几个map,到底是有什么用嘞?都代表什么含义?
singletonObjects:用于保存beanName和bean实例;
singletonFactories: 保存beanName和创建bean的工厂,ObecjtFactory就存在这里;
earlySingletonObjects: 保存beanName和bean实例,但是可以在bean创建过程中被拿到;
顺带一提,registeredSingletons: 保存当前所有已注册的bean
那么这一段代码的作用,简单来说就是:1 尝试从singletonObjects拿创建好的bean,如果有,返回;
如果没有—》2 从earlySingletonObjects查找有没有所需bean,如果有,返回;
如果还没有-------》3 从singletonFactories拿半成品bean,即ObjectFactory,从而拿到bean;
3.1.2 缓存中获取成功,进一步获取bean实例
接下来,就是详细阅读源码的部分了。话不多说,先来源码提提神:
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 1 验证FactoryBean,同时非FactoryBean的不处理
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
}
}
if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
Object object = null;
if (mbd == null) {
object = this.getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean)beanInstance;
if (mbd == null && this.containsBeanDefinition(beanName)) {
mbd = this.getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = mbd != null && mbd.isSynthetic();
// 2 将从FactoryBean中获取bean的工作交给getObjectFromFactoryBean处理;
object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
} else {
return beanInstance;
}
}
简单梳理一下这个方法都干了啥:
1 验证FactoryBean,同时非FactoryBean的不处理
2 将从FactoryBean中获取bean的工作交给getObjectFromFactoryBean处理;
这个方法的重点就在于getObjectFromFactoryBean如何把所需bean解析出来。
所以,跟进getObjectFromFactoryBean:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && this.containsSingleton(beanName)) {
synchronized(this.getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = this.doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
if (shouldPostProcess) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
return object;
}
this.beforeSingletonCreation(beanName);
try {
object = this.postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable var14) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var14);
} finally {
this.afterSingletonCreation(beanName);
}
}
if (this.containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
} else {
Object object = this.doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = this.postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var17);
}
}
return object;
}
}
代码一长,老实说就有点抗拒。但是看源码,不是一行一行的看懂每一个字才算看懂,要学会看到其关键方法和步骤。
前面说过,开头带do的,往往是干活的函数。而在这个方法里,正好就有一个do开头的方法,就是doGetObjectFromFactoryBean方法。
根据经验,这里大概率就是真正从FactoryBean里拿到所需bean的方法了。
跟进doGetObjectFromFactoryBean:
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = this.getAccessControlContext();
try {
object = AccessController.doPrivileged(factory::getObject, acc);
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
object = factory.getObject(); //关键一行
}
} catch (FactoryBeanNotInitializedException var7) {
throw new BeanCurrentlyInCreationException(beanName, var7.toString());
} catch (Throwable var8) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);
}
if (object == null) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
这么多行的代码,其实关键的一行看到即可。
object = factory.getObject();
了解FactoryBean的应该懂了哈。这里就是为了拿到FactoryBean里的对象。其他的代码,都是对参数的一些修饰判断罢了。
回过头来看的话,其实这个方法的名字,已经把他要做的事都实话实说了。
3.2 缓存中没有,开始创建单例bean
在上面2.1中doGetBean方法的第一个注释8的位置,有如下一段代码:
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
可以看到,对于缓存中没有的单例bean,这里也用了一个叫getSingleton的方法去获取,只不过使用的不是从缓存中取bean时提到的getSingleton方法,而是同名的另一个重载方法。
这里先不看createBean方法,而是先进入这个getSingleton的重载方法看看:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized(this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
// 1 检查这个bean在缓存中有没有;
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 2 beforeSingletonCreation记录加载状态;
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
// 3 由于传入的singletonFactory其类型为ObjectFactory,所以这里singletonFactory.getObject()是在获取bean;
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
// 4 将结果添加到缓存并删除加载过程中的各种辅助记录
this.addSingleton(beanName, singletonObject);
}
}
// 5 返回处理结果
return singletonObject;
}
}
又是一大段代码。。。。。。
总结一下这段代码,其主要做了如下5步内容:
1 检查这个bean在缓存中有没有;
2 beforeSingletonCreation记录加载状态;
3 由于传入的singletonFactory其类型为ObjectFactory,所以这里singletonFactory.getObject()是在获取bean;
4 addSingleton(beanName, singletonObject)加入缓存;
5 返回singletonFactory.getObject()获取到的bean;
这里有个要留意的点:singletonFactory是哪里来的呢?
方法的参数之一提供的。
类型呢?=======》ObjectFactory<?>
有没有很熟悉呢? 在3.1.1中,有提到这个类型的用处。
接下来,就是继续探索产生singletonFactory的方法=====》 createBean 方法了。
3.3 准备创建bean
进入createBean方法,又是一长串代码。具体源码如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
}
Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var10) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
}
try {
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
throw var7;
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
}
}
那么这里还是整理下这个方法的主要工作。这段代码,可以简化为如下的代码:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
~~~~~~~~~~~~巴拉巴拉巴~~~~~~~~~~~~~~~~
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]); //锁定class,根据设置的class属性或className解析class;
try {
mbdToUse.prepareMethodOverrides(); //对override属性进行标记及验证;
} catch (~~~~~~~~~ {
~~~~~~~~~~~~~
}
Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse); //跟beanProcessor一个机会返回代理,该代理会代替真正的实例;
if (beanInstance != null) {
return beanInstance;
}
~~~~~~~~
} catch (~~~~~~~~~~~) {
~~~~~~~~~~~~~~~~~
}
try {
beanInstance = this.doCreateBean(beanName, mbdToUse, args); //do开头,这个方法就是创建bean的真正方法;
~~~~~~~~~~~~~~~
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
throw var7;
} ~~~~~~~~~~~~~
}
this.resolveBeforeInstantiation(beanName, mbdToUse) 方法,看其方法名称,叫给个机会,是在创建bean前出现。如果这个方法的返回值不为null,则直接会返回beanInstance,从而不进行bean的创建。其内部代码为:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = bean != null;
}
return bean;
}
这个方法,基本就是对后置处理的调用;
同时,resolveBeforeInstantiation这个方法和其下的判断,也和AOP有关;
3.4 循环依赖
1 循环依赖的定义:
两个或多个bean互相持有对方;例如A类中有成员变量B类,B类中有成员变量C类,C类中又有成员变量A类。
2 三种循环依赖的情况以及spring的处理:
第一种,构造器循环依赖:无法解决,只能抛出异常;因为在构造方法里的循环依赖,会构成一个环。比如A在创建时,发现构造器里需要B,那么此时会去创建B,B创建时发现构造器需要C,同理,C创建要A,构成一个环,死局;
第二种,setter循环依赖:通过spring容器提前暴露只完成了构造器单未完成其他注入的bean来完成,并且仅限于单例模式;
这个提前暴露的bean,其实就是一个ObjectFactory;
第三种,prototype模式下的依赖处理:处理不了;
3.5 创建Bean
前面说到真正做事的方法往往以do开头,那么doCreateBean就是做事的了,如下为经过简化后的doCreateBean源码:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
~~~~~~~~
if (mbd.isSingleton()) { //若为单例,先清除缓存中key为beanName的bean
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) { //如果缓存中没有,则实例化
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
~~~~~~~~
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); //bean合并后的处理,Autowired在此实现类型的预解析;
} ~~~~~~~~~
~~~~~~~
//是否单例&&是否需要提前曝光&&当前bean是否在创建
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
~~~~~~~~~~
//循环依赖处理
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
//属性填充
this.populateBean(beanName, mbd, instanceWrapper);
//初始化bean
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} ~~~
~~~~~~~~~~~~~~~
//循环依赖检查
if (earlySingletonExposure) {
~~~~~~~~~~~~~
}
try {
//注册配置了destroy-method的bean
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
//将已经经过一系列处理的bean返回
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
3.5.1 创建bean的实例
创建bean的第一步,从如下方法开始:
if (instanceWrapper == null) { //如果缓存中没有,则实例化
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
进入createBeanInstance方法看看:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
~~~~~~~~~~~~~~
if (resolved) {
//根据构造函数自动注入进行构造,或者使用无参构造方法构造
return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
} else {
Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args) ?
//根据构造函数自动注入进行构造,或者使用无参构造方法构造
this.instantiateBean(beanName, mbd) : this.autowireConstructor(beanName, mbd, ctors, args);
}
}
}
}
这里说一下,一个bean对应的类中可能会有多个构造函数,且参数不同,spring会判断到底使用哪一个构造函数进行构造。
autowireConstructor就是根据有参的构造函数进行构造;instantiateBean是调用无参构造进行构造的。
3.5.2 属性注入populateBean
if (bw == null) {
~~~~~~~~~~~·
if (mbd.getResolvedAutowireMode() == 1) {
this.autowireByName(beanName, mbd, bw, newPvs);
}
if (mbd.getResolvedAutowireMode() == 2) {
this.autowireByType(beanName, mbd, bw, newPvs);
}
~~~~~~~~~~~~~~~
if (pvs != null) {
this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
}
}
}
值得注意的点,就是上面所示的三点,分别为:
1 autowireByName 根据名称自动注入;
2 autowireByType 根据类型自动注入;
3 applyPropertyValues 将属性应用到bean中;
感觉只要前两步就可以了,为什么会有第三步呢?
因为在自动注入时,会把需要的依赖放入PropertyValues中,而applyPropertyValues的作用则是真正把这些依赖注入已经实例化的bean中。
3.5.3 初始化bean—>initializeBean
这个方法代码不长,直接上原汁原味的源码:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
依然总结一下主要流程:
1 invokeAwareMethods: 激活Aware方法;
2 applyBeanPostProcessorsBeforeInitialization:后置处理器的使用;
3 初始化bean;
4 applyBeanPostProcessorsAfterInitialization:后置处理器的使用;
首先,这里介绍一下什么是Aware方法。
spring提供了一些Aware相关接口,常见的接口如BeanFactoryAware、ApplicationContextAware等,一个bean如果实现了这些接口,根据所实现的接口,就可以获得相应的资源。比如ApplicationContextAware接口,实现了该接口的bean,可以被注入ApplicationContext的实例,即拿到spring容器。
跟进invokeAwareMethods,如下所示,就是判断bean是否实现了部分Aware接口:
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 = this.getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(this);
}
}
}
后置处理器的使用,即对于BeanPostProcessor的实现,从而实现 applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization方法,在bean初始化前后进行增强;
3.5.4 返回创建好的bean
try {
//注册配置了destroy-method的bean
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
//将已经经过一系列处理的bean返回
return exposedObject;
}
4 打完收工
好了,到这里,bean的加载也就告一段落。基本上spring加载bean的骨架已经介绍完毕,虽然不是所有细节都面面俱到,但是对于初学源码的同学应该信息量足够了。