欢迎大家关注 github.com/hsfxuebao ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈
本文主要分析bean的创建过程。
1. refresh()
// 容器刷新的十二大步骤
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
...
// Instantiate all remaining (non-lazy-init) singletons.
// 11. 【大核心】bean创建:完成BeanFactory 初始化(工厂里面所有的组件都好了)
/*
* 这个方法一定要理解要具体看
* 1、bean实例化过程
* 2、ioc
* 3、注解支持
* 4、BeanPostProcessor的执行
* 5、Aop的入口
*/
finishBeanFactoryInitialization(beanFactory);
...
}
...
}
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
...
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化所有 非懒加载的单实例的bean
beanFactory.preInstantiateSingletons();
}
public void preInstantiateSingletons() throws BeansException {
...
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 创建出所有的单实例bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 单实例 & 非抽象&不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是FactoryBean
if (isFactoryBean(beanName)) {
//
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
// 不是FactoryBean则执行这个逻辑,普通的单实例非懒加载bean的创建
else {
// todo
getBean(beanName);
}
}
}
我们知道了 Spring 在容器刷新的后期 通过调用AbstractApplicationContext#finishBeanFactoryInitialization
方法来实例化了所有的非惰性bean。在这里面就通过 beanFactory.preInstantiateSingletons()
; 调用了一个非常关键的方法 AbstractBeanFactory#getBean(java.lang.String)
,而其实际上调用的是 AbstractBeanFactory#doGetBean
方法。
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
如果说,Spring中,Bean 的发现是在 ConfigurationClassPostProcessor
中进行的。那么Bean的创建就是在 doGetBean方法中进行的。 doGetBean 完成了单例Bean的完整创建过程,包括bean的创建,BeanPostProcessor 的方法调用、init-method等方法的调用、Aware 等接口的实现
。下面,我们开始来分析这个 doGetBean。
关于Bean 的加载过程,AbstractApplicationContext#finishBeanFactoryInitialization
经过几次跳转,最终会跳转到 AbstractBeanFactory#doGetBean 方法。每个bean的创建都会经历此方法,所以本文的主要内容是分析 AbstractBeanFactory#doGetBean
。
2. DefaultListableBeanFactory
需要强调的是,本文中调用 doGetBean 方法的是 AbstractBeanFactory 的子类DefaultListableBeanFactory
。如下图:
DefaultListableBeanFactory
结构图如下:
DefaultListableBeanFactory
是 Spring默认的BeanFactory类型。
注意这里说的
BeanFactory
并不是指ApplicationContext
,而是ApplicationContext
内部的一个BeanFactory
。
2.1 DefaultSingletonBeanRegistry
在这里我们只需要知道DefaultListableBeanFactory
继承了 DefaultSingletonBeanRegistry
类,拥有了 DefaultSingletonBeanRegistry
一系列的 集合类型来保存Bean相关信息。
大体如下,其中我们主要只需要关注前四个即可:
/** Cache of singleton objects: bean name to bean instance. */
// 用于保存BeanName和创建bean实例之间的关系,即缓存bean。 beanname -> instance
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
// 用于保存BeanName和常见bean的工厂之间的关系。beanname-> ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
// 也是保存BeanName和创建bean实例之间的关系,与singletonObjects 不同的是,如果一个单例bean被保存在此,则当bean还在创建过程中(比如 A类中有B类属性,当创建A类时发现需要先创建B类,这时候Spring又跑去创建B类,A类就会添加到该集合中,表示正在创建),就可以通过getBean方法获取到了,其目的是用来检测循环引用。
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */
// 用来保存当前所有已经注册的bean
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** Names of beans that are currently in creation. */
// 用来保存当前正在创建的Bean。也是为了解决循环依赖的问题
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** Names of beans currently excluded from in creation checks. */
// 用来保存当前从创建检查中排除的bean名称
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** List of suppressed Exceptions, available for associating related causes. */
// 初始化过程中的异常列表
@Nullable
private Set<Exception> suppressedExceptions;
/** Flag that indicates whether we're currently within destroySingletons. */
// 标志是否在销毁BeanFactory过程中
private boolean singletonsCurrentlyInDestruction = false;
/** Disposable bean instances: bean name to disposable instance. */
// 一次性bean实例:beanName -> 一次性实例。暂未明白
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
// 包含的Bean名称之间的映射:BeanName -> Bean包含的BeanName集合
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
/** Map between dependent bean names: bean name to Set of dependent bean names. */
// bean dependent(依赖的集合) : beanName -> 依赖该beanName 的 bean,即 key代表的bean 被value 所依赖
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
// bean 被哪些bean依赖 : beanName -> beanName 所依赖的 bean。即 key 依赖于value这些bean
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
2.1.1 关键缓存
下面挑出来几个关键缓存集合来描述:
singletonObjects
:ConcurrentHashMap。最简单最重要的缓存Map。保存关系是 beanName :bean实例关系。单例的bean在创建完成后都会保存在 singletonObjects 中,后续使用直接从singletonObjects 中获取。singletonFactories
:HashMap。这是为了解决循环依赖问题,用于提前暴露对象,保存形式是beanName : ObjectFactory<?>
。earlySingletonObjects
:HashMap。这也是为了解决循环依赖问题。和 singletonFactories 互斥。因为 singletonFactories 保存的是 ObjectFactory。而earlySingletonObjects 个人认为是 singletonFactories 更进一步的缓存,保存的是 ObjectFactory#getObject的结果。registeredSingletons
:LinkedHashSet,用于保存注册过的beanName。singletonsCurrentlyInCreation
: 保存当前正在创建的bean。当一个bean开始创建时将保存其beanName,创建完成后将其移除dependentBeanMap
:保存bean的依赖关系,比如A对象依赖于 B对象,会出现 B :A。即保存的是key 被value依赖dependenciesForBeanMap
:保存bean的依赖关系,不过和dependentBeanMap 反了过来。A对象依赖于 B对象,会出现 A :B。保存的是key 依赖于 value
我们拿一个简单的场景解释一下 singletonFactories
和 earlySingletonObjects
的关系 。 下面的代码是 DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
。我们可以看到其判断逻辑,
- 锁定
singletonObjects
,毕竟要操作singletonObjects
- 从
singletonFactories
中获取ObjectFactory
缓存 - 如果存在
ObjectFactory
缓存,则更进一步提取ObjectFactory#getObject
的singletonObject
对象。将singletonObject
保存到earlySingletonObjects
缓存中,同时从singletonFactories
中移除。
// DCL
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 检查单例缓存池 中有没有
Object singletonObject = this.singletonObjects.get(beanName); // 以及缓存
// 如果当前bean正在创建中,而且缓存中没有则继续
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // 三级缓存
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
2.1.2 图解
补上一张图,来看一看 A,B循环依赖 singletonFactories
和 earlySingletonObjects
的变化
在创建过程中会被添加到
singletonFactories
中,但当bean被循环依赖时
会被添加到earlySingletonObjects
中。也即是说earlySingletonObjects
中的bean都是被循环依赖的。
2.2 BeanDefinition
这里简单介绍一下,顾名思义,BeanDefinition
是bean的信息,一个BeanDefinition
描述和定义了创建一个bean需要的所有信息,属性,构造函数参数以及访问它们的方法。还有其他一些信息,比如这些定义来源自哪个类等等。
对于XML 配置方式的Spring方式来说, BeanDefinition
是配置文件 < bean >
元素标签在容器中的内容表示形式。<bean>
元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition 则提供了相应的beanClass、scope、lazyinit属性,BeanDefinition 和 <bean>
中的属性是一一对应
的。其中RootBeanDefinition
是最常用的实现类,一般对应< bean >
元素标签。
类似下图的定义:
需要注意的是 BeanDefinition 是一个接口,在Spring 中存在多种实现,具体请参考:blog.csdn.net/andy_zhang2… www.cnblogs.com/loongk/p/12…
3. doGetBean:bean的加载
下面我们开始进入正题,进行 AbstractBeanFactory#doGetBean
的内容分析。这个方法是一切的核心(Bean的创建过程也是在这个方法中完成)。首先我们先来整体过一遍方法代码。后面将会对一些关键点进行详细解释。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 1. 提取出对应的beanName。会去除一些特殊的修饰符比如 "&"
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
// 2. 尝试从缓存获取或者singletonFacotries中的ObjectFactory中获取。后续细讲
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
...
// 3. 返回对应的实例,有时候存在诸如FactoryBean的情况并不直接返回实例本身,
// 而是返回指定方法返回的实例。这一步主要还是针对FactoryBean的处理。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} // 默认第一次获取组件都会走到else中
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 4. 只有单例情况才会尝试解决循环依赖,原型模式直接抛出异常。因为原型模式无法解决循环依赖问题。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 拿到整个BeanFactory的父工厂,从父工厂中尝试获取组件
BeanFactory parentBeanFactory = getParentBeanFactory();
// 5. 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包含beanName,则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 递归到BeanFactory中检测
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果不仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
// 这里是将 当前创建的beanName 保存到 alreadyCreated 集合中。
// alreadyCreated 中的bean表示当前bean已经创建了,在进行循环依赖判断的时候会使用
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 6. 将当前 beanName 的 BeanDefinition 和父类BeanDefinition 属性进行一个整合
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 7. 寻找bean的依赖: 获取初始化的依赖项
String[] dependsOn = mbd.getDependsOn();
// 如果需要依赖,则递归实例化依赖bean
if (dependsOn != null) {
// 看当前的bean 有没有依赖 其他Bean
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
// 依赖了其他Bean,就先获取其他的Bean
getBean(dep);
}
...
}
}
// Create bean instance. 创建bean的实例
// 8 针对不同的Scope 进行bean的创建
// 实例化依赖的bean便可以实例化mdb本身了
// singleton 模式的创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// todo 创建bean实例
return createBean(beanName, mbd, args);
}
...
});
// 检查当前bean是否是 FactoryBean
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
// Prototype 模式的创建
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 指定scope上实例化bean
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
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, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
...
finally {
beanCreation.end();
}
}
// 9 类型转换, 转Object为bean信息
return adaptBeanInstance(name, beanInstance, requiredType);
}
@SuppressWarnings("unchecked")
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
// Check if required type matches the type of the actual bean instance.
// 检查需要的类型是否符合bean 的实际类型
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) convertedBean;
}
...
}
return (T) bean;
}
综上所属,doGetBean的 大体流程如下:
- 将传入的beanName 转化为合适的beanName。因为这里可能传入bean的别名,比如
FactoryBean
这里就是传入 “&beanName” , 这一步就会将其转化为 “beanName” - 尝试从单例缓存中获取 bean,主要是尝试从
singletonObjects
和singletonFactories
中获取实例。(这一步中还使用了earlySingletonObjects
来判断循环依赖的问题) - 如果第二步获取到了bean,则会针对处理 FactoryBean 这种特殊情况,以获取到正确的bean。(因为Factorybean 的话可能需要将其 getObject 方法的返回值作为bean注入到容器中)。
- 如果第二步没有获取到bean,则会检测其原型模式下的循环依赖情况,如果原型模式下有循环依赖,则直接抛出异常,因为原型模式下无法解决循环依赖。
- 如果第四步没有抛出异常,则会判断 当前
BeanFactory
中是否包含该beanName 的定义信息,如果不包含,则会递归去 parentBeanFactory 中去寻找beanName的定义信息. - 随后查询beanName 的
BeanDefinition
是否具有 父类的BeanDefinition, 如果有,则将 父类的一些属性和子类合并,形成一个新的BeanDefinition : mdb - 获取mdb中的
depends-on
属性,优先将依赖的bean创建,随后再创建当前bean。 - 到这一步,则说明当前bean尚未创建,则会根据 singleton 或者 prototype 或其他逻辑,走不同的流程来创建bean
- 创建bean结束后,根据调用者需要的类型进行一个类型转换。比如调用者希望返回一个Integer,这里得到的结果却是String,则会进行一个类型的转换。
3.1 转换 beanName
final String beanName = transformedBeanName(name);
这一步的目的是为了去除 beanName 的别名,获取bean的真正beanName。
这里的name传入的可能是 bean的别名,或者是FactoryBean类型的bean
。所以需要一系列的解析,解析包括:
- 去除 FactoryBean 的修饰符。也就是说如果 name = “&name” 或者 name = “&&name” 这种多&& 情况也会去除& 使得 name = “name”。
- 取指定alias所表示的最终beanName。比如别名A指向B的bean,则会返回B。
代码如下:
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
....
// 从别名中获取真正的beanName
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// 从aliasMap 中获取到真实的beanName
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
....
// BeanFactoryUtils 中
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// 如果不是以 & 开头直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 否则剪切到 开头的 & ,直至开头没有 &
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
3.2 尝试从缓存中加载单例
Object sharedInstance = getSingleton(beanName);
对于单例Bean来说, Spring只会在同一容器中创建一次,并将创建好的Bean 实例保存到 singletonObjects
中,下次再获取bean实例,直接从 singletonObjects 中获取。
这一步的目的是从尝试从缓存中获取实例。需要注意的是,Spring为了解决循环依赖问题, 在创建bean的原则是不等bean 创建完成就会将创建bean的ObjectFactory提早曝光加入到singletonFactories
缓存中,一旦下一个bean创建时需要依赖上一个bean,则直接使用ObjectFactory。 关于循环依赖的更多问题,后面会介绍。
代码逻辑如下:
- 尝试从
singletonObjects
中获取Bean 实例。获取不到说明该bean尚未创建成功 isSingletonCurrentlyInCreation
返回 true,则说明当前bean 的创建过程存在循环依赖。下面的逻辑就是为了尝试解决循环依赖- 尝试从
earlySingletonObjects
中获取,获取不到说明该bean并未在创建过程中。(为了解决循环依赖的问题) - 当
allowEarlyReference = true
时,这个是针对循环引用的操作,是允许循环引用。 - 随后 从
singletonFactories
中加载ObjectFactory
,并将结果保存到earlySingletonObjects
中,同时将singletonFactories
中关于bean的定义移除。(earlySingletonObjects 和 singletonFactories 互斥)
这里我们看到
singletonFactories
的映射关系是 beanName : ObjectFactoryearlySingletonObjects
的映射关系是 beanName : ObjectFactory#getObject
earlySingletonObjects
是singletonFactories
更进一步的缓存,所以二者互斥,相同的对象,一个缓存中存在即可。
具体代码如下:
// DCL
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 检查单例缓存池 中有没有
Object singletonObject = this.singletonObjects.get(beanName); // 以及缓存
// 如果当前bean正在创建中,而且缓存中没有则继续
// 单例缓存中没有对象 && 当前单例bean正在创建中,这是为了解决循环依赖的问题
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 如果此时bean正在加载(bean 在 earlySingletonObjects 中),则直接将singletonObject 返回。
singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存
// allowEarlyReference = true 才会允许循环依赖
if (singletonObject == null && allowEarlyReference) {
// 如果单例缓存中不存在该bean,则加锁进行接下来的处理
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 当某些方法需要提前初始化的时候则会调用addSingletonFactory
// 将对应的ObjectFactory初始化策略存储在singletonFactories中
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // 三级缓存
if (singletonFactory != null) {
// 调用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
// 记录在缓存中,earlySingletonObjects 和 singletonFactories互斥
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
3.3 尝试从FactoryBean中获取对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
当我们结束上一步之后,经过 sharedInstance != null && args == null
的判断后就会调用该方法。作为上一步获取到的结果 sharedInstance 。我们需要判断其是否是 FactoryBean 的 实现类,如果是,则需要将其getObject() 的结果注入
。所以该方法的功能简单来说就是用来检测当前bean是否是FactoryBean类型的bean,如果是,则调用其getObject() 方法,并将其返回值作为bean。
代码逻辑大体如下:
- 首先是在
AbstractBeanFactory#getObjectForBeanInstance
中 判断程序是否想获取 FactoryBean实例(beanName 是否以 & 开头)。如果是判断当前beanInstance是否是FactoryBean
。如果是则返回,否则抛出异常 - 如果不是想获取FactoryBean,那么就是想获取bean实例了。那么判断此时的beanInstance是普通的bean还是FactoryBean类型,如果是普通的bean则直接返回。
- 此时beanInstance 必定是 FactoryBean类型并且程序想获取bean实例。那么首先尝试从缓存 factoryBeanObjectCache 中获取。获取失败,则调用FactoryBean#getObject 方法来获取bean实例。并且在允许调用后置方法的情况下(shouldPostProcess 为true),调用
BeanPostProcessor#postProcessAfterInitialization
的方法。
下面我们来看详细代码
3.3.1 AbstractBeanFactory#getObjectForBeanInstance
调用了 AbstractBeanFactory#getObjectForBeanInstance:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// 1. 检测name 是否是想获取 工厂类 (name 以 & 开头)
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 以&开头又不是FactoryBean实现类,则抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// 2. 此时bean可能是 FactoryBean 或者 普通的bean。判断如果 beanInstance 不是 FactoryBean而是普通的bean, 就直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 3. 到这一步就可以确定,当前beanInstance 是FactoryBean,并且需要获取getObject() 的结果
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 尝试从缓存中加载bean。这一步是从 factoryBeanObjectCache 集合中获取
// 在后面获取 bean 成功后,可能会将 其缓存到 factoryBeanObjectCache 中
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// containsBeanDefinition 检测 beanDefinitionMap中也就是所有已经加载的类中检测是否定义beanName
if (mbd == null && containsBeanDefinition(beanName)) {
// 合并父类bean 定义的属性
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 4. 这一步中对FactoryBean进行了解析。
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
3.3.1.1 doGetObjectFromFactoryBean
getObjectFromFactoryBean 方法中 调用 doGetObjectFromFactoryBean 方法来获取 FactoryBean 中的 bean实例。下面我们来看一下getObjectFromFactoryBean 代码:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 判断是否是单例模式 && singletonObjects 尚未缓存该bean (containsSingleton调用的是 singletonObjects )
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 尝试从 factoryBeanObjectCache 缓存中获取
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 在这个方法中进行解析。调用 FactoryBean 的 getObject 方法
object = doGetObjectFromFactoryBean(factory, beanName);
// 因为是单例模式,所以要保证变量的全局唯一。所以这里如果缓存中已经创建好了bean则替换为已经创建好的bean
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
// 如果允许调用bean的后置处理器。因为这里是直接将bean创建返回了,如果要调用后置方法则只能在这里调用。
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 将beanName 添加到 singletonsCurrentlyInCreation 中缓存,表示当前bean正在创建中
beforeSingletonCreation(beanName);
try {
// 调用了ObjectFactory的后置处理器。
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
// 将beanName 从 singletonsCurrentlyInCreation 中移除,表示当前bean已经创建结束
afterSingletonCreation(beanName);
}
}
// return this.singletonObjects.containsKey(beanName); 如果 singletonObjects缓存中存在当前beanName,则将其缓存到 factoryBeanObjectCache 中。
if (containsSingleton(beanName)) {
// 这里保存的是 beanName : FactoryBean
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// FactoryBean 非单例直接调用 getObject 方法
Object object = doGetObjectFromFactoryBean(factory, beanName);
// 如果允许调用后置方法,则调用postProcessObjectFromFactoryBean 方法
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
3.4 原型模式的依赖检查 - isPrototypeCurrentlyInCreation
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
后面会对循环依赖进行详细介绍,简而言之就是 单例模式下才会尝试去解决循环依赖的问题,而原型模式则无法解决。也就是 isPrototypeCurrentlyInCreation
返回true,则抛出异常。
需要注意的是还有一个 方法是 判断单例模式的依赖检查 : isSingletonCurrentlyInCreation
3.5 递归 parentBeanFactory
这一步的逻辑比较简单,如下:
- 首先通过
containsBeanDefinition(beanName)
方法判断当前beanFactory中是否有bean的定义,如果有,皆大欢喜。直接进入下一步。 - 如果没有,且 parentBeanFactory 不为空,则会通过递归的方式,尝试从 parentBeanFactory 中加载bean定义。
// 5. 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包含beanName,则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 递归到BeanFactory中检测
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
其中 DefaultListableBeanFactory#containsBeanDefinition 代码如下
@Override
public boolean containsBeanDefinition(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return this.beanDefinitionMap.containsKey(beanName);
}
3.6 合并 BeanDefinition
BeanDefinition 顾名思义,就是关于bean 的定义信息。通过xml的bean定义可以很清楚的看到一些属性定义。
所以这一步就是检查当前 BeanDefinition 是否有父BeanDefinition ,如果有将一些属性和当前bean合并,生成一个 RootBeanDefinition。
推荐阅读: blog.csdn.net/andy_zhang2…
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
这一块的调用链路:getMergedLocalBeanDefinition -> getMergedBeanDefinition -> getMergedBeanDefinition
。所以我们 这里直接来看 getMergedBeanDefinition
方法。
首先,mdb 即 MergedBeanDefinition 的缩写,即一个合并的beanDefinition。
// 如果给定bean的定义是子bean定义,则通过与父级合并返回RootBeanDefinition。
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
// 判断如果parentName为空则没必要进行合并了,直接克隆返回即可
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
// 转换beanName
String parentBeanName = transformedBeanName(bd.getParentName());
// 递归调用,解析更上层的parent BeanDefinition
if (!beanName.equals(parentBeanName)) {
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
// 深拷贝
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
3.7 寻找依赖
这一步也是针对 BeanDefinition
的 dependsOn
属性来说的(对应注解则是 @DependsOn
。主要是 优先加载Bean 的 depends-on依赖。
注:在 BeanDefinition
加载过程中,通过扫描路径加载的时候,通过 ClassPathBeanDefinitionScanner#doScan
方法时会调用AnnotationConfigUtils#processCommonDefinitionAnnotations
来进行BeanDefinition 封装,其中就包含了诸多注解的解析,如下:
// 解读所有bean定义信息需要感知的注解
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
因为bean 的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺寻中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖。
// 获取依赖项
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 判断是否有循环依赖的情况 : A依赖B,B依赖A
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册依赖信息,将依赖信息保存到 dependentBeanMap、dependenciesForBeanMap中
registerDependentBean(dep, beanName);
try {
// 获取依赖的bean,这一步又回到了最初的getBean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
下面我们来看一看 isDependent(beanName, dep)
的处理逻辑
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
// 是否已经检测过了,上层一直是null
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
// 格式化beanName
String canonicalName = canonicalName(beanName);
// 获取 依赖于 beanName 的 bean集合
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
// 如果 依赖于 beanName中存在 dependentBeanName 则说明存在循环依赖。
// 代码走到这里说明是beanName 创建过程中要依赖 dependentBeanName。但是dependentBeans.contains(dependentBeanName) = true 则说明dependentBeanName依赖于beanName
// 造成了 A依赖B,B依赖A的情况
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
// 递归,确定没有A->B->C-A 这种长链路的循环依赖情况
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
注: @DependsOn
:注解是在另外一个实例创建之后才创建当前实例,也就是,最终两个实例都会创建,只是顺序不一样 @ConditionalOnBean
:注解是只有当另外一个实例存在时,才创建,否则不创建,也就是,最终有可能两个实例都创建了,有可能只创建了一个实例,也有可能一个实例都没创建
3.8 bean创建
上面这么多逻辑,都是准备工作。确定缓存中没有当前bean,并且当前bean的创建合法。准备开始创建。不过这里考虑到不同的 Scope,所以针对不同的Scope进行不同的初始化操作。创建bean 的过程也很复杂。
下面代码就是根据 Singleton、Prototype 或者其他Scope 走不同的流程创建bean。
// Create bean instance.
if (mbd.isSingleton()) {
// 单例的创建
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 解决FactoryBean的问题
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
// 原型模式的回调
Object prototypeInstance = null;
try {
// 保存当前线程正在创建的beanName 到 prototypesCurrentlyInCreation 中
beforePrototypeCreation(beanName);
// 直接创建bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 移除当前线程正在创建的beanName 从 prototypesCurrentlyInCreation 中
afterPrototypeCreation(beanName);
}
// 解决FactoryBean的问题
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final 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, () -> {
// 保存当前线程正在创建的beanName 到 prototypesCurrentlyInCreation 中
beforePrototypeCreation(beanName);
try {
// 创建bean
return createBean(beanName, mbd, args);
}
finally {
// 移除当前线程正在创建的beanName 从 prototypesCurrentlyInCreation 中
afterPrototypeCreation(beanName);
}
});
// 解决FactoryBean的问题
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
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",
ex);
}
}
关于 bean 创建的过程 getSingleton
,下面进行分析。
3.9 类型转换
到这里整个流程基本就结束了。通常对该方法的调用参数 requiredType
是null,。但某些情况可能会出现返回的bean是个String类型,但是requiredType 传入的却是Integer类型,这时候就会触发这一步的操作,将String类型转换为Integer类型。
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
4. getSingleton:bean的获取
DefaultSingletonBeanRegistry#getSingleton(java.lang.String, ObjectFactory<?>)
这一步创建了bean,我们来分析 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法整个流程。
4.1 获取单例 - getSingleton
如下, 是整个 getSingleton方法的代码,做了一些基本注释
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 因为创建过程中需要操作 singletonObjects。所以需要加锁
synchronized (this.singletonObjects) {
// 1. 再次尝试获取bean,判断bean是否已经加载。如果加载直接返回。
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 2. 判断,如果当前beanFactory正在被销毁则直接抛出异常,不允许创建单例bean
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 (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 3. 做一些bean创建前的准备工作: 记录beanName 正在加载的状态(添加到 singletonsCurrentlyInCreation 缓存中),若bean已经正在加载,则抛出异常。为了解决循环引用的问题
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 4. 通过回调方式获取bean实例。
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 5. 加载单例后的处理方法调用 : 删除bean正在创建的记录(从 singletonsCurrentlyInCreation 中移除 beanName)
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 6. 加入到缓存中,并删除加载bean过程中所记录的各种辅助状态
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
...
// 主要还是对几个缓存map的操作
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);
}
}
...
// 不包含 && 添加失败 :则认为Bean正在创建中,抛出异常
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
...
// 不包含 && 移除失败 :认为Bean 已经创建结束,抛出异常。
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
上面的代码注释也比较清楚,基本流程如下:
this.singletonObjects.get(beanName)
; :再次尝试从缓存中获取bean,若获取到,则直接返回。if (this.singletonsCurrentlyInDestruction)
:未获取到检测bena是否正在销毁,若是则抛出异常beforeSingletonCreation
方法中记录bean正在创建的状态将beanName添加到singletonsCurrentlyInCreation集合中)。在循环依赖时可根据此判断。singletonObject = singletonFactory.getObject()
; :调用 ObjectFactory.getObject() 方法来实例化beanafterSingletonCreation
方法移除bean正在夹杂的状态addSingleton(beanName, singletonObject);
: 对各种缓存状态做处理。
流程图如下所示 :下面的流程图关于 beforeSingletonCreation 和 afterSingletonCreation 的注释写的有些问题,正确的描述如下:
inCreationCheckExclusions
不包含 beanName && singletonsCurrentlyInCreation 添加失败 :则认为Bean正在创建中,抛出异常inCreationCheckExclusions
不包含 beanName && singletonsCurrentlyInCreation 移除失败 :认为Bean 已经创建结束,抛出异常。
可以非常直观的看出, getSingleton 方法中的关键逻辑非常简单,bean创建的具体逻辑在 singletonObject = singletonFactory.getObject();
中,所以下面继续去分析singletonFactory.getObject()
中做了什么。
4.2 创建bean - createBean概述
上面可以看到,主要步骤还是在回调的 getObject() 方法中。那么我们来看看在bean加载过程中的FactoryBean做了什么。代码如下:
兜了一大圈关键代码还是在createBean 方法里。接下来,我们就来仔细分析一下 createBean 方法。
AbstractAutowireCapableBeanFactory#createBean
方法代码如下 ,附带部分注释:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// 1. 锁定class, 根据mdb和 beanName 解析出来 class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 2. 验证及准备覆盖的方法
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 3. 调用BeanProcessors的方法来替代真正的实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果后处理器真的实现了,则直接返回使用后处理器的bean
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 4. 创建bean 的 真正方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
可以看到,createBean 的整体流程大致如下:
- 根据设置的class属性或者根据className来解析Class。
- 对override 属性进行标记及验证。
- 应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作。
- 创建bean。
- 返回bean
流程图如下:
上面的逻辑看着似乎不复杂,实际上,真正的逻辑都被封装在了方法中,所以下面需要关注如下的几个方法:
4.2.1 resolveBeanClass
这里不再过多展示代码,这个方法的作用就是根据参数和返回值都能知道: 根据 BeanDefinition和 beanName 解析出 bean 的Class。
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
4.2.2 prepareMethodOverrides
见名知意: 准备方法重写,这里更多是做一个校验的功能。这个方法主要是针对 lookup-method 和 replaced-method 两个属性的,用来覆盖指定的方法。
mbdToUse.prepareMethodOverrides();
详细代码如下:
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exist and determine their overloaded status.
// 判断是否有方法需要重写
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
// 获取对应的类中的对应方法名的个数
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
// 等于0抛出异常。上面已经验证有方法需要覆盖,这里为0肯定错误
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
// 标记 MethodOverride 暂未被覆盖,避免参数类型检查的开销。
mo.setOverloaded(false);
}
}
解释一下上面的逻辑:
- 首先会判断是否有方法需要重写,这里的是根据 RootBeanDefinition 中的 methodOverrides 属性来进行判断,为空则表示没有。
- 若上述判断有方法需要覆盖,则会调用prepareMethodOverride(MethodOverride mo) 方法。而在 prepareMethodOverride(MethodOverride mo) 方法中会根据 需要覆盖的方法名称 来获取加载类中关于该方法的实现。如果获取不到 count == 0,则直接抛出异常,如果获取到只有一个 count == 1,则记录该方法并未被重载(因为Spring在方法匹配时,如果一个类中存在若干个重载方法,则在函数调用及增强的时候需要根据参数类型进行匹配,来最终确定调用的方法是哪一个,这里直接设置了该方法并未被重载,在后续方法匹配的时候就不需要进行参数匹配验证,直接调用即可)。
- 打个比方,比如指定覆盖A类中的 a方法,但是A类中可能存在多个a方法或者不存在a方法,若count == 0不 存在a方法,则谈何覆盖,直接抛出异常,若count ==1 则a方法的实现只有一个,标记该方法并未被重载后续可跳过参数验证的步骤。
4.2.3 resolveBeforeInstantiation
该方法主要是调用 InstantiationAwareBeanPostProcessor
来进行一些处理,这里实际上是给了用户一次代替Spring来创建bean的机会,代码实现上非常简单直接调用的后处理器方法。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果通过后置处理器创建出来bean,则直接返回创建的bean
if (bean != null) {
return bean;
}
该方法调用了后处理器的方法:
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
: 在bean初始化前调用BeanPostProcessor#postProcessAfterInitialization
: 在bean初始化后调用- 关于后置处理器部分具体介绍请看Spring5源码5-Bean生命周期后置处理器
详细代码如下:在调用 doCreate 方法创建bean的实例前调用了该方法对 BeanDefinition 中的属性做一些前置处理。
@Nullable
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.
// 当前类并非合成类 && 存在 BeanPostProcessor (后处理器)
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 1. 获取目标类
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 2. 实例前的后处理器应用
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 3. 实例后的后处理器应用
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
其中 applyBeanPostProcessorsBeforeInstantiation
和 applyBeanPostProcessorsAfterInitialization
很明显就是调用bean的后置处理器,也就是对后置处理器中的 InstantiationAwareBeanPostProcessor
类型的后处理器进行 postProcessBeforeInstantiation 方法
和 BeanPostProcessor 类型的 postProcessAfterInitialization 方法
的调用。
4.2.3.1 determineTargetType(beanName, mbd);
关于 factoryMethodName 值的由来,即如果通过@Bean 注入,则保存期工厂类的方法名称,简单来说就是配置类中对应该bean的注入方法名称。
@Nullable
protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
// 获取目标类。这里获取的目标类并不一定是真正生成的类,可能是其真正类的父类或者父接口
Class<?> targetType = mbd.getTargetType();
if (targetType == null) {
// 根据mdb 是否存在 factoryMethodName 来确定是直接解析class还是通过 工厂类的方法返回值来获取class
targetType = (mbd.getFactoryMethodName() != null ?
getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
resolveBeanClass(mbd, beanName, typesToMatch));
if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
mbd.resolvedTargetType = targetType;
}
}
return targetType;
}
需要注意的是 这里获取的 targetType
类型并不一定是真正生成的bean类型,也可能是实际类型 的父类或者父接口 。因为对于通过 @Bean 注解修饰注入到Spring容器的时候,BeanDefinition
的 factoryMethodName
属性值不为空,指向其工厂类的方法名。并且由于多态的特性,其工厂方法引入的类型并不一定是实际类型。这个类型的错误会在AbstractAutowireCapableBeanFactory#doCreateBean
中纠正过来.
比如 :下面的 demoService()方法实际生成的类型是 DemoServiceImpl。这里返回的类型是DemoService 。那么我们这里获取到的 targetType 就是 DemoService.class。其 BeanDefinition.factoryMethodName = demoService (即 DemoConfig 生成DemoService的方法的名称)
public class DemoConfig {
@Bean
public DemoService demoService() {
return new DemoServiceImpl();
}
}
4.2.3.2 postProcessBeforeInstantiation
在bean 实例化前调用,也就是将 AbstractBeanDefinition 转换为 BeanWrapper 前的处理。给子类一个修改BeanDefinition的机会,也就是说当程序经过这个方法后,bean可能已经不是我们所认为的bean了。或许是一个经过代理的代理bean。可能是通过cglib生成的,也可能是通过其他技术生成的。
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
// 获取所有 BeanPostProcessor 进行遍历
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 调用 postProcessBeforeInstantiation 方法
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
4.2.3.3 postProcessAfterInitialization
这里是bean创建后的后置方法调用,逻辑基本类似。不同的是到达这一步时,Bean已经创建成功,并且注入属性也进行了赋值。
需要注意,如果bean交由Spring来创建,那么Spring会将需要的属性注入到bean中,如果是自己代理生成(比如 通过 postProcessBeforeInstantiation 方法生成),那么需要自己解决bean的属性注入问题。
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
4.3 创建bean - doCreateBean
代码执行到这里,可以确定第三步中并没有返回一个非空的bean(BeanPostProcessor 并没有代理生成一个bean)。所以Spring开始自己着手创建bean。do开头的方法才是真正做事情的,所以这里才是真正创建bean的地方。
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
doCreateBean 代码如下,带有详细注释:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
// 是否单例
if (mbd.isSingleton()) {
// 单例情况下清除缓存。这里保存的是 FactoryBean 和 BeanWrapper 的映射关系。
// factoryBeanInstanceCache 是在创建其他bean的时候缓存了一下 FactoryBean 。
// 至于单例模式下移除而不是获取,因为单例只需要创建一次 ? 尚未理解。
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 如果没有缓存,则重新创建
if (instanceWrapper == null) {
// todo 创建Bean实例 ,默认使用无参构造器创建的对象,组件的实例就创建了
// 1. 根据指定的bean使用对应的策略创建新的实例。如:工厂方法、构造函数自动注入,简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取bean实例
Object bean = instanceWrapper.getWrappedInstance();
// 获取bean类型
Class<?> beanType = instanceWrapper.getWrappedClass();
// 将目标类型替换成实际生成的类型.纠正了上面说到类型错误(如果存在)
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// MergedBeanDefinitionPostProcessor 后置处理器再来修改下BeanDefinition 信息
// 2. 调用 MergedBeanDefinitionPostProcessor 后处理器
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// todo 执行MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()方法
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 提前暴露 单实例bean 专门来解决循坏引用的问题
// 3. 判断是否需要提早曝光 : 单例 & 允许循环依赖 & 当前bean已经正在创建中
// 由于当前bean已经在创建中,本次创建必然是循环引用造成的,所以这里判断是否可以需要提前曝光
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");
}
// 添加
// 三级缓存中Bean也会被后置处理来增强
// 4. 为避免后期循环依赖,在bean初始化完成前将创建实例的ObjectFactory 加入工程 -- 解决循环依赖
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// todo 对象中的每个属性赋值
// 5. 对bean进行属性填充,将各个属性值注入,其中如果存在依赖于其他bean的属性,则会递归初始依赖bean
populateBean(beanName, mbd, instanceWrapper);
// todo 初始化Bean
// 调用初始化方法,比如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 早期单实例暴露
// 6. 进行循环依赖检查
if (earlySingletonExposure) {
// 检查早期缓存中是否存在这个组件
// earlySingletonReference 只有在检测到有循环依赖的情况下才会不为空
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 如果 exposedObject没有在初始化方法中被改变,也就是没有被增强
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);
}
}
// 因为bean创建后其所依赖的bean一定是已经创建了的。
// actualDependentBeans不为空说明当前 bean创建后其依赖的bena却没有全部创建完,也就说说存在循环依赖。
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
// 7.根据Scopse 注册bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
可以看到大致逻辑如下:
createBeanInstance(beanName, mbd, args)
:实例化bean,将BeanDefinition转换为BeanWrapperapplyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
: MergedBeanDefinitionPostProcessor 后处理器的应用。bean合并后的处理,比如 @Autowired、@Value注解正是通过AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
此方法实现的预解析。addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
: 关于循环依赖的处理,添加 ObjectFactory到singletonFactories缓存中,同时这里给了用户一个机会通过调用 SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference 方法来由用户生成暴露的实例populateBean(beanName, mbd, instanceWrapper);
:对创建的bean内部的一些属性进行填充注入initializeBean(beanName, exposedObject, mbd);
: 初始化bean的一些属性,如Aware 接口的实现, init-method属性等- 循环依赖检查。和第四步不同的是,这里了是判断是否无法解决循环依赖,否则抛出异常。
registerDisposableBeanIfNecessary(beanName, bean, mbd);
: 注册DisposableBean- 完成创建并返回。
doCreatebean 方法的代码量非常大,这里由于篇幅问题,需要新开篇分析,所以本文中挑选几个简单的方法分析,复杂的方法新开篇分析。
4.3.1 createBeanInstance
见名知意 : 该方法完成了bean的实例创建。
instanceWrapper = createBeanInstance(beanName, mbd, args);
大概逻辑可以概括为:
- 如果存在工厂方法则使用工厂方法进行初始化
- 若类有多个构造函数,则根据参数锁定构造函数并初始化
- 如果即不存在工厂方法也不存在带参构造函数,则使用默认的构造函数进行bean的实例化。
这里详细见第5小节分析。
4.3.2 applyMergedBeanDefinitionPostProcessors
这种方法命名的也见得多了,见名知意: 该方法完成了 MergedBeanDefinitionPostProcessors 后处理器的功能。主要是 bean合并后的处理。在 AutowiredAnnotationBeanPostProcessor对postProcessMergedBeanDefinition方法的实现中,就对@Autowired、@Value 等注解进行了一系列的预处理,这里我们并不需要太过在意。
关于 AutowiredAnnotationBeanPostProcessor 的内容,后面单独开一篇来分析。
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
详细代码如下,不再具体分析
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
4.3.3 addSingletonFactory
这一部分的逻辑就是为了解决循环依赖的问题,将未创建完成的当前bean,通过ObjectFactory进行一个包装,提前暴露给其他bean。
我们实际的分析是一部分代码块如下:
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");
}
// 这里为了避免后期的循环依赖,在bean初始化前将创建实例的ObjectFactory加入工厂中。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
首先我们需要分析出 earlySingletonExposure 为true的条件:
- bean是单例
- 允许循环依赖
- 当前bean正在创建中 : singletonsCurrentlyInCreation 包含当前bean。在Spring 中 有专门的属性记录 bean的加载状态 – DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation。在bean创建前会将bean添加,bean创建结束后将bean移除。这一点我们在前篇有过提及。
满足上述三个条件后,则会 调用 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
方法。这个方法作用是将正在创建的bean缓存起来,主要目的还是用来解决循环依赖的问题。
详细代码如下:
// 对一系列缓存map 做处理。在 singletonFactories 中保存 ObjectFactory 类型,进行提前暴露
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
// 如果singletonObjects不存在(bean未创建成功)
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
...
// 给调用者一次机会,主要就是调用了SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference 方法。将getEarlyBeanReference 方法的返回值作为提前暴露的对象。
// 我们可以通过实现 getEarlyBeanReference 方法来替代Spring提前暴露的对象
// Aop 就是在这里将 Advice 动态织入bean中,若没有bean则直接返回bean,不做任何处理
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
该方法中 getEarlyBeanReference
调用了后处理器的方法,可用于用户自己扩展替换Spring生成的提前暴露的对象 :
SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference (Object bean, String beanName);
4.3.4 populateBean
见名知意,下面这个方法是用来属性注入的。 populateBean 方法则是对bean 属性的注入,上面的 createBeanInstance
方法创建了 bean,但是其内部属性并没有注入,比如通过 @Autowired 注解注入的变量属性,此时还为null,需要对这种属性进行注入,这一步就是完成这种功能。
populateBean(beanName, mbd, instanceWrapper);
在这里方法里按照如下顺序调用了后处理器
-
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
: 返回true 才会调用下面两个方法InstantiationAwareBeanPostProcessor.postProcessProperties
: 进行属性的注入。InstantiationAwareBeanPostProcessor.postProcessPropertyValues
: 已过时 详细的代码分析后面分析。
4.3.5 initializeBean
到达这一步,其实bean已经创建结束了,这一步是完成最后的功能,提供一些功能的实现,如Aware 接口的实现, init-method、InitializingBean属性等。
exposedObject = initializeBean(beanName, exposedObject, mbd);
详情后面分析
4.3.6 循环依赖检查
Spring 循环依赖的解决仅对单例且非构造函数构造的形式有效,对于原型模式的bean,Spring直接抛出异常,在这个步骤中会检测已经加载的bean 是否已经出现了循环依赖,并判断是否需要抛出异常。
// earlySingletonExposure 为true 说明要校验循环依赖的问题
if (earlySingletonExposure) {
// 调用了 getSingleton 方法获取缓存中的对象,这里注意传递的false。
Object earlySingletonReference = getSingleton(beanName, false);
// 如果 earlySingletonReference 不为空,则说明存在循环依赖
if (earlySingletonReference != null) {
// 如果缓存的对象 exposedObject == bean,直接赋值之前暴露出来的bean
// 这里
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// allowRawInjectionDespiteWrapping 默认false && beanName 被其他bean依赖
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 获取依赖于 当前bean的 beanName
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
//
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// 如果 actualDependentBeans 不为空,则抛出循环依赖的异常
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
...
// 上面调用的 getSingleton 方法。可以知道这里传递的 allowEarlyReference 为false。
// 因为当前bean在进行循环创建的时候,就已经将 bean缓存到 earlySingletonObjects 中了
// DCL
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 检查单例缓存池 中有没有
Object singletonObject = this.singletonObjects.get(beanName); // 以及缓存
// 如果当前bean正在创建中,而且缓存中没有则继续
// 单例缓存中没有对象 && 当前单例bean正在创建中,这是为了解决循环依赖的问题
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 如果此时bean正在加载(bean 在 earlySingletonObjects 中),则直接将singletonObject 返回。
singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存
// allowEarlyReference = true 才会允许循环依赖
if (singletonObject == null && allowEarlyReference) {
// 如果单例缓存中不存在该bean,则加锁进行接下来的处理
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 当某些方法需要提前初始化的时候则会调用addSingletonFactory
// 将对应的ObjectFactory初始化策略存储在singletonFactories中
ObjectFactory<?> singletonFactory = 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名称的单例实例(如果有的话),但前提是该类型仅用于类型检查以外的用途。
protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
removeSingleton(beanName);
return true;
}
else {
return false;
}
}
...
protected void removeSingleton(String beanName) {
synchronized (getSingletonMutex()) {
super.removeSingleton(beanName);
this.factoryBeanObjectCache.remove(beanName);
}
}
...
// super.removeSingleton(beanName); 如下
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
关于这一段的逻辑参考 : blog.csdn.net/qq_18297675…
整个逻辑如下:
getSingleton(beanName, false);
: 从缓存中获取缓存对象,这传递的false, 直接从earlySingletonObjects
中获取循环依赖的对象earlySingletonReference
。- 如果 earlySingletonReference == bean ,说明bean没有被修改,直接赋值即可。
- 如果 earlySingletonReference != bean ,那么说明 在 下面的代码中,bean被修改了
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
此时需获取依赖于当前bean的 dependentBeans。如果dependentBeans 中有已经创建好的,那么则抛出异常
4.3.7 registerDisposableBeanIfNecessary
这一步的目的是实现 destory-method 属性,如果bean配置了该属性,则需要注册以便在销毁时调用。
详细代码如下:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
// 单例模式下注册需要销毁的bean,此方法会处理实现DisposableBean的bean
// 并且对所有的bean使用 DestructionAwareBeanPostProcessor 处理 DisposableBean DestructionAwareBeanPostProcessor
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
// 自定义 scope 的处理
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
篇幅有限,剩下的几个核心方法,下一篇文章阐述,敬请期待。
参考文章
Spring5源码注释github地址
Spring源码深度解析(第2版)
spring源码解析
Spring源码深度解析笔记
Spring注解与源码分析
Spring注解驱动开发B站教程