其中比较重要的功能是对 BeanFactory 中 getBean 方法的实现。
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return this.doGetBean(name, requiredType, (Object[])null, false);
}
public Object getBean(String name, Object... args) throws BeansException {
return this.doGetBean(name, (Class)null, args, false);
}
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException {
return this.doGetBean(name, requiredType, args, false);
}
内部调用 doGetBean()
方法,这个方法的代码比较长,各位耐心看下:
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
// 获取 beanName,这里是一个转换动作,将 name 转换Wie beanName
String beanName = this.transformedBeanName(name);
/*
*检查缓存中的实例工程是否存在对应的实例
*为何要优先使用这段代码呢?
*因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
*spring创建bean的原则是在不等bean创建完就会将创建bean的objectFactory提前曝光,即将其加入到缓存中,一旦下个bean创建时依赖上个bean则直接使用objectFactory
*直接从缓存中或singletonFactories中获取objectFactory
*就算没有循环依赖,只是单纯的依赖注入,如B依赖A,如果A已经初始化完成,B进行初始化时,需要递归调用getBean获取A,这是A已经在缓存里了,直接可以从这里取到
*/
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
if (this.logger.isTraceEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//返回对应的实例,有些时候并不是直接返回实例,而是返回某些方法返回的实例
//这里涉及到我们上面讲的FactoryBean,如果此Bean是FactoryBean的实现类,如果name前缀为"&",则直接返回此实现类的bean,如果没有前缀"&",则需要调用此实现类的getObject方法,返回getObject里面真是的返回对象
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
//只有在单例的情况下才会解决循环依赖
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//尝试从parentBeanFactory中查找bean
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);
}
if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
return parentBeanFactory.getBean(nameToLookup);
}
//如果不是仅仅做类型检查,则这里需要创建bean,并做记录
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
try {
//将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,同时如果存在父bean的话则合并父bean的相关属性
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
this.checkMergedBeanDefinition(mbd, beanName, args);
//如果存在依赖则需要递归实例化依赖的bean
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];
// 若给定的依赖 bean 已经注册为依赖给定的b ean
// 循环依赖的情况
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本身进行实例化
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
// 显示从单利缓存中删除 bean 实例
// 因为单例模式下为了解决循环依赖,可能它已经存在了,所以销毁它
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 {// 从指定的 scope 下创建 bean
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;
}
}
// 检查需要的类型是否符合 bean 的实际类型
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.isTraceEnabled()) {
this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
} else {
return bean;
}
}
代码是相当长,处理逻辑也是相当复杂,下面将其进行拆分讲解。
String beanName = this.transformedBeanName(name);
这里传递的是 name,不一定是 beanName,可能是 aliasName,也有可能是 FactoryBean(带“&”前缀),所以这里需要调用 transformedBeanName()
方法对 name 进行一番转换。
AbstractBeanFactory 类中的 transformedBeanName()方法:
protected String transformedBeanName(String name) {
return this.canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
BeanFactoryUtils 类中的 transformedBeanName()方法:
// 去除 FactoryBean 的修饰符
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
return !name.startsWith("&") ? name : (String)transformedBeanNameCache.computeIfAbsent(name, (beanName) -> {
do {
beanName = beanName.substring("&".length());
} while(beanName.startsWith("&"));
return beanName;
});
}
SimpleAliasRegistry 类中的 canonicalName()方法:
// 转换 aliasName
public String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
do {
resolvedName = (String)this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
} while(resolvedName != null);
return canonicalName;
}
主要处理过程包括两步:
name = "&studentService"
,则会是 name = "studentService"
。单例在 Spring 的同一个容器中只会被创建一次,后续再获取 bean 直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再尝试从 singletonFactorry 加载。因为在创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring 创建 bean 的 时候不等 bean 创建完成就会将创建 bean 的 ObjectFactory 提早加入到缓存中,一旦下一个 bean 创建时需要依赖上个 bean,则直接使用 ObjectFactory;就算没有循环依赖,只是单纯的依赖注入,如果B依赖A,如果A已经完成初始化,B进行初始化时,需要递归调用 getBean 获取A,这时A已经在缓存里了,直接可以从这里取到。接下来我们看下获取单例 bean 的方法 getSingleton(beanName)
,进入方法体:
@Nullable
public Object getSingleton(String beanName) {
//参数true是允许早期依赖
return this.getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//检查缓存中是否存在实例,这里就是上面说的单纯的依赖注入,如B依赖A,如果A已经初始化完成,B进行初始化时,需要递归调用getBean获取A,这是A已经在缓存里了,直接可以从这里取到
Object singletonObject = this.singletonObjects.get(beanName);
//如果缓存为空且单例bean正在创建中,则锁定全局变量,为什么要判断bean在创建中呢?这里就是可以判断是否循环依赖了。
//A依赖B,B也依赖A,A实例化的时候,发现依赖B,则递归去实例化B,B发现依赖A,则递归实例化A,此时会走到原点A的实例化,第一次A的实例化还没完成,只不过把实例化的对象加入到缓存中,但是状态还是正在创建中,由此回到原点发现A正在创建中,由此可以判断是循环依赖了
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
//如果此bean正在加载,则不处理
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//当某些方法需要提前初始化的时候会直接调用addSingletonFactory把对应的ObjectFactory初始化策略存储在singletonFactory中
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//使用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
//记录在缓存中,注意earlySingletonObjects和singletonFactories是互斥的
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
这里涉及到很多个存储bean的不同map,简单解释下:
这个方法先尝试从 singletonObjects 里面获取实例,如果如果获取不到再从 earlySingletonObjects 里面获取,如果还获取不到,再尝试从 singletonFactories 里面获取 beanName 对应的 ObjectFactory,然后再调用这个 ObjectFactory 的 getObject 方法创建 bean,并放到 earlySingletonObjects 里面去,并且从 singletonFactoryes 里面 remove 掉这个 ObjectFactory,而对于后续所有的内存操作都只为了循环依赖检测时候使用,即 allowEarlyReference 为 true 的时候才会使用。
从缓存中获取到 bean 以后就要获取实例对象了,这里用到的是 getObjectForBeanInstance 方法。getObjectForBeanInstance 是个频繁使用的方法,无论是从缓存中获得 bean 还是根据不同的 scope 策略加载 bean。总之,我们得到 bean 的实例后,要做的第一步就是调用这个方法来检测一下正确性,其实就是检测获得的 bean 是不是 FactoryBean 类型的 bean,如果是,那么需要调用该 bean 对应的 FactoryBean 实例中的 getObject()作为返回值。接下来我们看下此方法的源码:
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//如果指定的name是工厂相关的(以&开头的)
if (BeanFactoryUtils.isFactoryDereference(name)) {
//如果是NullBean则直接返回此bean
if (beanInstance instanceof NullBean) {
return beanInstance;
} else if (!(beanInstance instanceof FactoryBean)) {//如果不是FactoryBean类型,则验证不通过抛出异常
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
} else {
//如果获取的beanInstance是FactoryBean类型,但是是以(以&开头的),也直接返回,此时返回的是FactoryBean的实例
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
} else if (!(beanInstance instanceof FactoryBean)) {//如果获取的beanInstance不是FactoryBean类型,则说明是普通的Bean,可直接返回
return beanInstance;
} else {
Object object = null;
// 若 BeanDefinition 为 null,则从缓存中加载
if (mbd != null) {
mbd.isFactoryBean = true;
} else {
object = this.getCachedObjectForFactoryBean(beanName);
}
// 若 object 依然为空,则可以确认,beanInstance 一定是 FactoryBean
if (object == null) {
FactoryBean<?> factory = (FactoryBean)beanInstance;
if (mbd == null && this.containsBeanDefinition(beanName)) {
mbd = this.getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = mbd != null && mbd.isSynthetic();
//到了这里说明获取的beanInstance是FactoryBean类型,但没有以"&"开头,此时就要返回factory内部getObject里面的对象了
object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
}
该方法功能如下:
getObjectFromFactoryBean()
方法处理接着我们来看看真正的核心功能 FactoryBeanRegistrySupport 类中的 getObjectFromFactoryBean(factory, beanName, !synthetic)方法中实现的,继续跟进代码:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 为单例模式且singletonObjects缓存中存在
if (factory.isSingleton() && this.containsSingleton(beanName)) {
synchronized(this.getSingletonMutex()) {
// 从缓存中获取指定的 factoryBean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 为空,则从 FactoryBean 中获取对象
object = this.doGetObjectFromFactoryBean(factory, beanName);
// 再从缓存中获取,不知出于什么考虑,不是已经加锁了吗
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
// 需要后续处理
if (shouldPostProcess) {
// 若该 bean 处于创建中,则返回非处理对象,而不是存储它
if (this.isSingletonCurrentlyInCreation(beanName)) {
return object;
}
// 前置处理
this.beforeSingletonCreation(beanName);
try {
// 对从 FactoryBean 获取的对象进行后处理
// 生成的对象将暴露给bean引用
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;
}
}
主要流程如下:
postProcessObjectFromFactoryBean()
进行后置处理。doGetObjectFromFactoryBean()
方法从 FactoryBean 获取对象,其实内部就是调用 FactoryBean.getObject()
。beforeSingletonCreation()
进行创建之前的处理。默认实现将该 bean 标志为当前创建的。postProcessObjectFromFactoryBean()
对从 FactoryBean 获取的 bean 实例对象进行后置处理,默认实现是按照原样直接返回,二次实现是在 AbstractAutowireCapableBeanFactory 中实现的,当然子类也可以重写它,比如应用后置处理。afterSingletonCreation()
进行创建 bean 之后的处理,默认实现是将该 bean 标记为不再在创建中。注意: beforeSingletonCreation()
、 afterSingletonCreation()
方法非常重要,因为它们记录着 bean 的加载状态,是检测当前 bean 是否处于创建中的关键之处,对解决 bean 循环依赖起着关键作用。但是需要注意的是,起作用并非是在这里,当执行 getSingleton(beanName, singletonFactory)
方法时,其中使用到上面两个方法,对解决 bean 循环依赖至关重要,关于循环依赖的问题可以翻看上一章节内容。
postProcessObjectFromFactoryBean()
是对从 FactoryBean 处获取的 bean 实例对象进行后置处理,其默认实现是直接返回 object 对象,不做任何处理,子类可以重写,例如应用后处理器。AbstractAutowireCapableBeanFactory 对其提供了实现,如下:
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
关于后置处理器,我们之前的文章有讲解过,只需要记住一点:尽可能保证所有 bean 初始化后都会调用注册的 BeanPostProcessor.postProcessAfterInitialization()
方法进行处理 ,在实际开发过程可以针对此特性涉及自己的业务逻辑。
在该方法中最为核心的方法是 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;
}
在调试过程中发现,如果 bean 声明为 FactoryBean 类型,则当提取bean时候提取的不是 FactoryBean,而是 FactoryBean 中对应的 getObject 方法返回的 bean,而 doGetObjectFromFactroyBean 正是实现这个功能。
在上面代码中还有一个非常重要的检测方法 isSingletonCurrentlyInCreation(beanName)
,该方法用于判断该 beanName 对应的 bean 是否在创建过程中,注意这个过程讲的是整个工厂中。如下:
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
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);
}
if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
return parentBeanFactory.getBean(nameToLookup);
}
主要流程为:
重点在于第二步,如果满足条件,首先执行 originalBeanName(name)
,其定义如下:
protected String originalBeanName(String name) {
String beanName = this.transformedBeanName(name);
if (name.startsWith("&")) {
beanName = "&" + beanName;
}
return beanName;
}
transformedBeanName()
是对 name 进行转换,获取真正的 beanName,因为我们传递的可能是 aliasName,如果 name 是以 “&” 开头的,则加上 “&”,因为在 transformedBeanName()
将 “&” 去掉了,这里补上。
之后的就是继续调用 doGetBean()方法。
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
// 加上全局锁
synchronized(this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
this.clearMergedBeanDefinition(beanName);
// 添加到已创建bean 集合中
this.alreadyCreated.add(beanName);
}
}
}
}
参数 typeCheckOnly 是用来判断调用 getBean()
是否为类型检查而不是获取 bean,默认值为 false,即不是做类型检查而是创建 bean。
获取 RootBeanDefinition
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
调用 getMergedLocalBeanDefinition()
获取相对应的 BeanDefinition,如下:
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
RootBeanDefinition mbd = (RootBeanDefinition)this.mergedBeanDefinitions.get(beanName);
return mbd != null && !mbd.stale ? mbd : this.getMergedBeanDefinition(beanName, this.getBeanDefinition(beanName));
}
首先直接从 mergedBeanDefinitions 缓存中获取相应的 RootBeanDefinition,如果存在则直接返回否则调用 getMergedBeanDefinition()
获取 RootBeanDefinition,若获取的 BeanDefinition 为子 BeanDefinition,则需要合并父类的相关属性。关于 BeanDefinition 的知识,后续我们会专门做讲解。
如果一个 bean 有依赖 bean 的话,那么在初始化该 bean 时是需要先初始化它所依赖的 bean。
// 在初始化 bean 时解析 depends-on 标签时设置
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];
// 检验依赖的bean 是否已经注册给当前 bean 获取其他传递依赖bean
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册到依赖bean中
this.registerDependentBean(dep, beanName);
try {
// 调用 getBean 初始化依赖bean
this.getBean(dep);
} catch (NoSuchBeanDefinitionException var24) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
}
}
}
通过迭代的方式依次对依赖 bean 进行检测、校验,如果通过则调用 registerDependentBean(dep, beanName)
方法将两个 bean 之间的依赖关系存起来,具体实现在 DefaultSingletonBeanRegistry 类中,关于该方法在上章节中讲述循环依赖时也提及到。 isDependent()
是校验该依赖是否已经注册给当前 bean。
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized(this.dependentBeanMap) {
return this.isDependent(beanName, dependentBeanName, (Set)null);
}
}
同步加锁给 dependentBeanMap 对象,然后调用 isDependent()
校验。dependentBeanMap 对象保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
// alreadySeen 已经检测的依赖 bean
if (alreadySeen != null && ((Set)alreadySeen).contains(beanName)) {
return false;
} else {
// 获取原始 beanName
String canonicalName = this.canonicalName(beanName);
// 获取当前 beanName 的依赖集合
Set<String> dependentBeans = (Set)this.dependentBeanMap.get(canonicalName);
// 不存在依赖,返回false
if (dependentBeans == null) {
return false;
} else if (dependentBeans.contains(dependentBeanName)) {// 存在,则证明存在已经注册的依赖
return true;
} else {
Iterator var6 = dependentBeans.iterator();
String transitiveDependency;
do {
if (!var6.hasNext()) {
return false;
}
transitiveDependency = (String)var6.next();
if (alreadySeen == null) {
alreadySeen = new HashSet();
}
((Set)alreadySeen).add(beanName);
} while(!this.isDependent(transitiveDependency, dependentBeanName, (Set)alreadySeen));
return true;
}
}
}
如果校验成功,则调用 registerDependentBean()
将该依赖进行注册,便于在销毁 bean 之前对其进行销毁。
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = this.canonicalName(beanName);
Set dependenciesForBean;
synchronized(this.dependentBeanMap) {
dependenciesForBean = (Set)this.dependentBeanMap.computeIfAbsent(canonicalName, (k) -> {
return new LinkedHashSet(8);
});
if (!dependenciesForBean.add(dependentBeanName)) {
return;
}
}
synchronized(this.dependenciesForBeanMap) {
dependenciesForBean = (Set)this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, (k) -> {
return new LinkedHashSet(8);
});
dependenciesForBean.add(canonicalName);
}
}
其实将就是该映射关系保存到两个集合中:dependentBeanMap、dependenciesForBeanMap。
最后调用 getBean()
实例化依赖 bean。这里和讲解 循环依赖 时不同,虽然都是递归进去调用 getBean()
方法,讲解循环依赖时是在 BeanDefinitionValueResolver 类中的 resolveReference()
方法内,进而调用 getBean()
方法。
在 Spring 中存在着不同的 scope,默认是 singleton ,还有 prototype、request 等等其他的 scope ,接下来我们分析一下它们的创建过程。
Spring 的 scope 默认为 singleton,其初始化的代码如下:
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,但是如果缓存中不存在呢?则需要从头开始加载 bean,这个过程由 getSingleton(beanName, singletonFactory)
实现。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 全局加锁
synchronized(this.singletonObjects) {
// 从缓存中检查一遍
// 因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
....
// 加载前置处理
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
// 初始化 bean
// 这个过程其实是调用 createBean() 方法,调试的时候可以发现
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
....
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 后置处理
this.afterSingletonCreation(beanName);
}
// 加入缓存中
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
其实这个过程并没有真正创建 bean,仅仅只是做了一部分准备和预处理步骤,真正获取单例 bean 的方法其实是由 singletonFactory.getObject()
这部分实现,而 singletonFactory 由回调方法产生。那么这个方法做了哪些准备呢?
beforeSingletonCreation()
记录加载单例 bean 之前的加载状态,即前置处理。getObject()
实例化 bean。afterSingletonCreation()
进行加载单例后的后置处理。这里我们看一下 addSingleton()
方法
protected void addSingleton(String beanName, Object singletonObject) {
synchronized(this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
结合循环依赖章节中所讲,这一步就是清除二级和三级缓存中的数据,添加到一级缓存中,位于一级缓存中的单例数据可以多次被调用。
接着来重点关注 AbstractAutowireCapableBeanFactory 类中实现的 createBean()方法,其定义如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 确保此时的 bean 已经被解析了
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
// 如果获取的class 属性不为null,则克隆该 BeanDefinition
// 主要是因为该动态解析的 class 无法保存到到共享的 BeanDefinition
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 {
// 给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例
// AOP 的功能就是基于这个地方
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 {
// 执行真正创建 bean 的过程
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isTraceEnabled()) {
this.logger.trace("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);
}
}
主要过程如下:
prepareMethodOverrides()
方法涉及到 BeanDefinition,后续会做介绍。
resolveBeforeInstantiation()
的作用是给 BeanPostProcessors 后置处理器返回一个代理对象的机会,其实在调用该方法之前 Spring 一直都没有创建 bean ,那么这里返回一个 bean 的代理类有什么作用呢?作用体现在后面的 if
判断:
if (beanInstance != null) {
return beanInstance;
}
如果代理对象不为空,则直接返回代理对象,这一步骤有非常重要的作用,Spring 后续实现 AOP 就是基于这个地方判断的。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
这个方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()
和 applyBeanPostProcessorsAfterInitialization()
两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。最终还是由 BeanPostProcessor 接口实现类来完成相应的工作。
接下来就该最核心的创建 bean 的工作,该过程有 doCreateBean()
实现,如下:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
BeanWrapper instanceWrapper = null;
// 单例模型,则从未完成的 FactoryBean 缓存中删除
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
// 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
// 包装的实例对象
Object bean = instanceWrapper.getWrappedInstance();
// 包装的实例对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 检测是否有后置处理
// 如果有后置处理,则允许后置处理修改 BeanDefinition
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
....
}
mbd.postProcessed = true;
}
}
// 解决单例模式的循环依赖
// 单例模式 & 运行循环依赖&当前单例 bean 是否正在被创建
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
// 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性
// 则会递归初始依赖 bean
this.populateBean(beanName, mbd, instanceWrapper);
// 调用初始化方法
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
/**
* 循环依赖处理
*/
if (earlySingletonExposure) {
// 获取 earlySingletonReference
Object earlySingletonReference = this.getSingleton(beanName, false);
// 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
if (earlySingletonReference != null) {
// 如果 exposedObject 没有在initializeBean初始化方法中被改变,也就是没有被增强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
....
}
}
}
}
try {
// 注册 bean
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
.....
}
}
整体的思路:
createBeanInstance()
实例化 bean,主要是将 BeanDefinition 转换为 BeanWrappercreateBeanInstance()
实例化 bean,赋零值populateBean()
属性填充initializeBean()
初始化 bean,包括前置、后置处理器的调用创建完 bean 实例后,还会执行 getObjectForBeanInstance()
方法,这个方法在缓存中获取单例 bean 一节有介绍到。
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);
}
原型模式的初始化过程很简单:直接创建一个新的实例就可以了。过程如下:
beforeSingletonCreation()
记录加载原型模式 bean 之前的加载状态,即前置处理。createBean()
创建一个 bean 实例对象。afterSingletonCreation()
进行加载原型模式 bean 后的后置处理。getObjectForBeanInstance()
从 bean 实例中获取对象。原型模式下,执行 createBean()
相对来说简单一些,这里就不多做介绍了。不过关于循环依赖队列中存在原型模式的 bean,需要注意一下,这里我们还是拿之前的案例来进行测试,做一下修改。
修改 beans.xml 文件,将其中的一个 bean 定义为原型模式:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="car" class="com.msdn.bean.AbstractCar" p:brand="宝马" p:money-ref="money" />
<bean id="person" class="com.msdn.bean.Person" p:name="herish" p:car-ref="car" />
<bean id="money" class="com.msdn.bean.Money" p:classification="工资" p:person-ref="person" scope="prototype"/>
beans>
新的测试代码:
@Test
public void cycleRely(){
ClassPathResource resource = new ClassPathResource("config/beans.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Person person = (Person) beanFactory.getBean("person");
System.out.println(person);
Money money = (Money) beanFactory.getBean("money");
Money money2 = (Money) beanFactory.getBean("money");
System.out.println(money == money2);
AbstractCar car = (AbstractCar) beanFactory.getBean("car");
AbstractCar car2 = (AbstractCar) beanFactory.getBean("car");
System.out.println(car == car2);
}
运行结果为:
Person{name='herish', 拥有一辆car=AbstractCar{brand='宝马', money=Money{classification='工资', person=herish}}}
false
true
从结果来看,貌似没什么问题,money 对象确实也不再是单例,循环依赖也处理成功了。接下来我们做一下修改:
@Test
public void cycleRely(){
ClassPathResource resource = new ClassPathResource("config/beans.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
// Person person = (Person) beanFactory.getBean("person");
// System.out.println(person);
Money money = (Money) beanFactory.getBean("money");
Money money2 = (Money) beanFactory.getBean("money");
System.out.println(money == money2);
AbstractCar car = (AbstractCar) beanFactory.getBean("car");
AbstractCar car2 = (AbstractCar) beanFactory.getBean("car");
System.out.println(car == car2);
}
运行该代码会报错:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'money' defined in class path resource [config/beans.xml]: Cannot resolve reference to bean 'person' while setting bean property 'person'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'person' defined in class path resource [config/beans.xml]: Cannot resolve reference to bean 'car' while setting bean property 'car'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'car' defined in class path resource [config/beans.xml]: Cannot resolve reference to bean 'money' while setting bean property 'money'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'money': Requested bean is currently in creation: Is there an unresolvable circular reference?
调试该代码可以发现问题,由于mbd.isSingleton()
(此处mbd为money对应的bean)为false,导致没有将相应的数据加入到三级缓存中,再次调用 getSingleton(beanName, allowEarlyReference)
方法返回结果为 null,导致进行到 isPrototypeCurrentlyInCreation(beanName)
方法时抛出异常。
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);
}
核心流程和原型模式一样,只不过获取 bean 实例是由 scope.get()
实现,如下:
public Object get(String name, ObjectFactory<?> objectFactory) {
// 获取 scope 缓存
Map<String, Object> scope = this.threadScope.get();
Object scopedObject = scope.get(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
// 加入缓存
scope.put(name, scopedObject);
}
return scopedObject;
}
AbstractBeanFactory 类中对于 getBean(name)
方法的讲解终于结束了,这也是 bean 加载的过程。