文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。
1. 概述
Spring IoC 容器的作用- Spring IoC 容器会以某种方式加载 Configuration Metadata,将其解析注册到容器内部,然后会根据这些信息绑定整个系统的对象,最终组装成一个可用的基于轻量级容器的应用系统。
- 流程分为两个阶段:容器初始化阶段 和 加载 bean 阶段。
- 容器初始化阶段。
-
步骤 1,通过某种方式加载 Configuration Metadata(主要依据
Resource
、ResourceLoader
两个体系)。 -
步骤 2,容器对加载的 Configuration MetaData 进行解析和分析,并将分析的信息组装成
BeanDefinition
。 -
步骤 3,将
BeanDefinition
保存注册到相应的BeanDefinitionRegistry
中。
-
步骤 1,通过某种方式加载 Configuration Metadata(主要依据
- 加载 Bean 阶段。
-
步骤 1,经过容器初始化阶段后,应用程序中定义的 bean 信息已经全部加载到系统中,当显示或者隐式地调用
BeanFactory#getBean()
方法时,触发加载 Bean 阶段。 - 步骤 2,容器首先检查所请求的对象是否已经初始化完成,如果没有,则会根据注册的 Bean 信息实例化请求的对象,并为其注册依赖,然后将其返回给请求方。
-
步骤 1,经过容器初始化阶段后,应用程序中定义的 bean 信息已经全部加载到系统中,当显示或者隐式地调用
- 容器初始化阶段。
- 流程分为两个阶段:容器初始化阶段 和 加载 bean 阶段。
- 容器初始化阶段的相关整理可以查看 【Spring 笔记】资源加载策略相关整理、【Spring 笔记】BeanDefinition 装载与注册相关整理、【Spring 笔记】Bean 解析相关整理。
2. 原理
2.1 getBean
- 显示或者隐式地调用
BeanFactory#getBean()
方法,会触发加载 Bean 阶段。
// AbstractBeanFactory.java
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean
参数 | 说明 |
---|---|
name | 要获取 Bean 的名字 |
requiredType | 要获取 bean 的类型 |
args | 创建 Bean 时传递的参数。这个参数仅限于创建 Bean 时使用。 |
typeCheckOnly | 是否只做类型检查。 |
// AbstractBeanFactory.java
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 1. 返回 bean 名称,剥离工厂引用前缀。
// 如果 name 是 alias ,则获取对应映射的 beanName 。
final String beanName = transformedBeanName(name);
Object bean;
// 从缓存中或者实例工厂中获取 Bean 对象
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 2. 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 3. 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 4. 如果容器中没有找到,则从父类容器中加载
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
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);
}
}
// 5. 如果不是仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 6. 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 7. 处理所依赖的 bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 若给定的依赖 bean 已经注册为依赖给定的 bean
// 循环依赖的情况
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 缓存依赖调用
registerDependentBean(dep, beanName);
try {
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 8. bean 实例化
// Create bean instance.
if (mbd.isSingleton()) { // 单例模式
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
// 显式从单例缓存中删除 Bean 实例
// 因为单例模式下为了解决循环依赖,可能他已经存在了,所以销毁它。 TODO 芋艿
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) { // 原型模式
// It's a prototype -> create a new instance.
Object prototypeInstance;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
// 从指定的 scope 下创建 bean
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, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
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);
}
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 9. 检查需要的类型是否符合 bean 的实际类型
// Check if required type matches the type of the actual bean instance.
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());
}
}
return (T) bean;
}
- 方法的调用流程。
- 步骤 1,获取 beanName。
- 步骤 2,从单例 Bean 缓存中获取 Bean。
- 步骤 3,原型模式依赖检查。
- 步骤 4,从 parentBeanFactory 获取 Bean。
- 步骤 5,将指定的 Bean 标记为已经创建或即将创建。
- 步骤 6,获取 BeanDefinition。
- 步骤 7,对依赖 Bean 的处理。
- 步骤 8,对不同作用域的 Bean 进行实例化。
- 步骤 9,类型转换。
2.1.1 获取 beanName
// AbstractBeanFactory.java
final String beanName = transformedBeanName(name);
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
- 因为这里的 name 不一定就是 beanName,可能是 aliasName ,也有可能是 FactoryBean ,调用
transformedBeanName()
方法,对 name 进行转换。 - 调用
BeanFactoryUtils#transformedBeanName()
方法,去除FactoryBean
的修饰符。- transformedBeanNameCache 集合的存在,是为了缓存转换后的结果。下次再获取相同的 name 时,直接返回缓存中的结果即可。
- 去除传入 name 参数的 " & " 的前缀。假设配置了一个
FactoryBean
的名字为 "abc" ,那么获取FactoryBean
创建的 Bean 时,使用 "abc" ,如果获取FactoryBean
本身,使用 "$abc" 。
// BeanFactoryUtils.java
/**
* Cache from name with factory bean prefix to stripped name without dereference.
*
* 缓存 {@link #transformedBeanName(String)} 已经转换好的结果。
*
* @since 5.1
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>();
/**
* 去除 FactoryBean 的修饰符 &
*
* 如果 name 以 “&” 为前缀,那么会去掉该 "&" 。
* 例如,name = "&studentService" ,则会是 name = "studentService"。
*
* Return the actual bean name, stripping out the factory dereference
* prefix (if any, also stripping repeated factory prefixes if found).
* @param name the name of the bean
* @return the transformed name
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { // BeanFactory.FACTORY_BEAN_PREFIX = $
return name;
}
// computeIfAbsent 方法,分成两种情况:
// 1. 未存在,则进行计算执行,并将结果添加到缓存、
// 2. 已存在,则直接返回,无需计算。
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
} while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
- 调用
canonicalName()
方法,取指定的 alias 所表示的最终 beanName 。- 一个循环获取 beanName 的过程,例如,别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 C。
// SimpleAliasRegistry.java
/** Map from alias to canonical name. */
// key: alias
// value: beanName
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
// 循环,从 aliasMap 中,获取到最终的 beanName
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
} while (resolvedName != null);
return canonicalName;
}
2.1.2 从单例 Bean 缓存中获取 Bean
- 单例模式的 Bean 在整个过程中只会被创建一次。第一次创建后会将该 Bean 加载到缓存中。后面,在获取 Bean 就会直接从单例缓存中获取。
// AbstractBeanFactory.java
// 从缓存中或者实例工厂中获取 Bean 对象
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 1. 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
- 方法的调用流程。
-
步骤 1,如果从缓存中得到了 Bean 对象,则需要调用
getObjectForBeanInstance()
方法,对 Bean 进行实例化处理。 - 缓存中记录的是最原始的 Bean 状态,得到的不一定是最终想要的 Bean 。
-
步骤 1,如果从缓存中得到了 Bean 对象,则需要调用
-
FactoryBean 的用途。
- Spring 通过反射机制利用 bean 的 class 属性指定实现类来实例化 bean ,某些情况下,实例化 bean 过程比较复杂,按照传统的方式,需要提供大量的配置信息,配置方式的灵活性是受限的。
- Spring 为此提供了一个 FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化 bean 的逻辑。
- Spring 自身提供了 70 多个 FactoryBean 的实现,它们隐藏了实例化一些复杂 bean 的细节,给上层应用带来了便利。
2.1.2.1 getSingleton
// DefaultSingletonBeanRegistry.java
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1. 从单例缓冲中加载 bean
Object singletonObject = this.singletonObjects.get(beanName);
// 2. 缓存中的 bean 为空,且当前 bean 正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 加锁
synchronized (this.singletonObjects) {
// 2. 从 earlySingletonObjects 获取
singletonObject = this.earlySingletonObjects.get(beanName);
// 3. earlySingletonObjects 中没有,且允许提前创建
if (singletonObject == null && allowEarlyReference) {
// 从 singletonFactories 中获取对应的 ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 获得 bean
singletonObject = singletonFactory.getObject();
// 添加 bean 到 earlySingletonObjects 中
this.earlySingletonObjects.put(beanName, singletonObject);
// 从 singletonFactories 中移除对应的 ObjectFactory
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
- 方法的调用流程。
- 步骤 1,从 singletonObjects 中,获取 Bean 对象。
- 步骤 2,若为空且当前 bean 正在创建中,则从 earlySingletonObjects 中获取 Bean 对象。
-
步骤 3,若为空且允许提前创建,则从 singletonFactories 中获取相应的
ObjectFactory
对象。- 若不为空,则调用其
ObjectFactory#getObject()
方法,创建 Bean 对象,然后将其加入到 earlySingletonObjects ,然后从 singletonFactories 删除。
- 若不为空,则调用其
- 根据 beanName 依次检测三个 Map,若为空,检查下一个,否则返回。
// DefaultSingletonBeanRegistry.java
/**
* Cache of singleton objects: bean name to bean instance.
*
* 存放的是单例 bean 的映射。
*
* 对应关系为 bean name --> bean instance
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* Cache of singleton factories: bean name to ObjectFactory.
*
* 存放的是 ObjectFactory,可以理解为创建单例 bean 的 factory 。
*
* 对应关系是 bean name --> ObjectFactory
**/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/**
* Cache of early singleton objects: bean name to bean instance.
*
* 存放的是早期的 bean,对应关系也是 bean name --> bean instance。
*
* 它与 {@link #singletonFactories} 区别在于 earlySingletonObjects 中存放的 bean 不一定是完整。
*
* 从 {@link #getSingleton(String)} 方法中,我们可以了解,bean 在创建过程中就已经加入到 earlySingletonObjects 中了。
* 所以当在 bean 的创建过程中,就可以通过 getBean() 方法获取。
*
* 这个 Map 也是【循环依赖】的关键所在。
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
isSingletonCurrentlyInCreation
- 该方法用于判断该 beanName 对应的 Bean 是否在创建过程中,这个过程讲的是整个工厂中。
- 在 Bean 创建过程中都会将其加入到 singletonsCurrentlyInCreation 集合中。
// DefaultSingletonBeanRegistry.java
/**
* Names of beans that are currently in creation.
*
* 正在创建中的单例 Bean 的名字的集合
*/
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
2.1.2.2 getObjectForBeanInstance
- 从缓存中获取 Bean 后,若其不为 null 且 args 为空,则会调用
getObjectForBeanInstance()
方法,进行处理。- 因为从缓存中获取的 bean 是最原始的 Bean ,并不一定是最终想要的 Bean ,调用
getObjectForBeanInstance()
方法进行处理,该方法的定义为获取给定 Bean 实例的对象,该对象要么是 bean 实例本身,要么就是FactoryBean
创建的 Bean 对象。
- 因为从缓存中获取的 bean 是最原始的 Bean ,并不一定是最终想要的 Bean ,调用
// AbstractBeanFactory.java
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 1. 若为工厂类引用(name 以 & 开头)
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
// 如果是 NullBean,则直接返回
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 如果 beanInstance 不是 FactoryBean 类型,则抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// 到这里我们就有了一个 Bean 实例,当然该实例可能是一个正常的 bean 又或者是一个 FactoryBean
// 如果是 FactoryBean,则创建该 Bean
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
// 2. 对非 FactoryBean 类型的处理
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
// 3. 若 BeanDefinition 为 null,则从缓存中加载 Bean 对象
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
// 若 object 依然为空,则可以确认,beanInstance 一定是 FactoryBean 。从而,使用 FactoryBean 获得 Bean 对象
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// containsBeanDefinition 检测 beanDefinitionMap 中也就是在所有已经加载的类中
// 检测是否定义 beanName
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
// 将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition,
// 如果指定 BeanName 是子 Bean 的话同时会合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
// 是否是用户定义的,而不是应用程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 核心处理方法,使用 FactoryBean 获得 Bean 对象
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
- 该方法主要是进行检测工作,方法的调用流程。
-
步骤 1,若 name 为工厂相关的(以 & 开头),且 beanInstance 为
NullBean
类型则直接返回,如果 beanInstance 不为FactoryBean
类型则抛出BeanIsNotAFactoryException
异常。这里主要是 校验 beanInstance 的正确性。 -
步骤 2,如果 beanInstance 不为
FactoryBean
类型或者 name 也不是与工厂相关的,则直接返回 beanInstance 这个 Bean 对象。这里主要是 对非FactoryBean
类型的处理。 -
步骤 3,如果
BeanDefinition
为空,则从 factoryBeanObjectCache 中加载 Bean 对象。- 如果还是空,则可以断定 beanInstance 一定是
FactoryBean
类型,则委托getObjectFromFactoryBean()
方法,进行处理,使用FactoryBean
获得 Bean 对象。
- 如果还是空,则可以断定 beanInstance 一定是
-
步骤 1,若 name 为工厂相关的(以 & 开头),且 beanInstance 为
getObjectFromFactoryBean
-
getObjectForBeanInstance()
方法,可以分成两种情况。- 当该实例对象为非
FactoryBean
类型,直接返回给定的 Bean 实例对象 beanInstance 。 - 当该实例对象为
FactoryBean
类型,从FactoryBean
( beanInstance ) 中,获取 Bean 实例对象,通过getObjectFromFactoryBean()
方法实现。
- 当该实例对象为非
// FactoryBeanRegistrySupport.java
/**
* Cache of singleton objects created by FactoryBeans: FactoryBean name to object.
*
* 缓存 FactoryBean 创建的单例 Bean 对象的映射
* beanName ===> Bean 对象
*/
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 1. 为单例模式且缓存中存在
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) { // 1.1. 单例锁
// 1.2. 从缓存中获取指定的 factoryBean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 为空,则从 FactoryBean 中获取对象
object = doGetObjectFromFactoryBean(factory, beanName);
// 从缓存中获取
// TODO 芋艿,具体原因
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
// 1.3. 需要后续处理
if (shouldPostProcess) {
// 若该 Bean 处于创建中,则返回非处理对象,而不是存储它
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 单例 Bean 的前置处理
beforeSingletonCreation(beanName);
try {
// 对从 FactoryBean 获取的对象进行后处理
// 生成的对象将暴露给 bean 引用
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
} finally {
// 单例 Bean 的后置处理
afterSingletonCreation(beanName);
}
}
// 1.4. 添加到 factoryBeanObjectCache 中,进行缓存
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
// 2.
} else {
// 为空,则从 FactoryBean 中获取对象
Object object = doGetObjectFromFactoryBean(factory, beanName);
// 需要后续处理
if (shouldPostProcess) {
try {
// 对从 FactoryBean 获取的对象进行后处理
// 生成的对象将暴露给 bean 引用
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
- 方法的调用流程。
-
步骤 1,若为单例且单例 Bean 缓存中存在 beanName ,则进行后续处理(跳转到下一步),否则,则执行 <步骤 2> 从
FactoryBean
中获取 Bean 实例对象。 - 步骤 1.1,获取锁。锁住的对象都是 this.singletonObjects,因为在单例模式中必须要保证 全局唯一。
-
步骤 1,若为单例且单例 Bean 缓存中存在 beanName ,则进行后续处理(跳转到下一步),否则,则执行 <步骤 2> 从
// DefaultSingletonBeanRegistry.java
/**
* Cache of singleton objects: bean name to bean instance.
*
* 存放的是单例 bean 的映射。
*
* 对应关系为 bean name --> bean instance
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
public final Object getSingletonMutex() {
return this.singletonObjects;
}
步骤 1.2,从 factoryBeanObjectCache 缓存中获取实例对象 object 。
- 若 object 为空,则调用
doGetObjectFromFactoryBean()
方法,从FactoryBean
获取对象,内部调用FactoryBean#getObject()
方法,获取 Bean 对象。
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
// 需要权限验证
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
// 从 FactoryBean 中,获得 Bean 对象
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
// 从 FactoryBean 中,获得 Bean 对象
object = factory.getObject();
}
} catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
-
步骤 1.3,如果需要后续处理(shouldPostProcess = true),则进行进一步处理。
- 若该 Bean 处于创建中(
isSingletonCurrentlyInCreation()
方法返回 true),则返回 非处理的 Bean 对象,而不是存储它。 - 调用
beforeSingletonCreation()
方法,进行创建之前的处理。默认实现是将该 Bean 标志为 当前创建的。 - 调用
postProcessObjectFromFactoryBean()
方法,对从FactoryBean
获取的 Bean 实例对象进行后置处理。 - 调用
afterSingletonCreation()
方法,进行创建 Bean 之后的处理,默认实现是将该 bean 标记为 不再在创建中。
- 若该 Bean 处于创建中(
- 步骤 1.4,加入到 factoryBeanObjectCache 缓存中。
-
beforeSingletonCreation()
和afterSingletonCreation()
记录着 Bean 的加载状态,是检测当前 Bean 是否处于创建中的关键之处,对解决 Bean 循环依赖起着关键作用。
beforeSingletonCreation
// DefaultSingletonBeanRegistry.java
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName)
&& !this.singletonsCurrentlyInCreation.add(beanName)) { // 添加
throw new BeanCurrentlyInCreationException(beanName); // 如果添加失败,则抛出 BeanCurrentlyInCreationException 异常。
}
}
afterSingletonCreation
- 移除,对 singletonsCurrentlyInCreation 集合进行 remove。
// DefaultSingletonBeanRegistry.java
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) &&
!this.singletonsCurrentlyInCreation.remove(beanName)) { // 移除
// 如果移除失败,则抛出 IllegalStateException 异常
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
postProcessObjectFromFactoryBean
- 对从
FactoryBean
处获取的 Bean 实例对象进行后置处理。默认实现是直接返回 object 对象,不做任何处理。
// DefaultSingletonBeanRegistry.java
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
return object;
}
- **org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory **抽象类,对其提供了实现。
// AbstractAutowireCapableBeanFactory.java
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
- 进行回调注册
BeanPostProcessors
,让能够后期处理从FactoryBean
中获取的对象。
// AbstractAutowireCapableBeanFactory.java
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 遍历 BeanPostProcessor
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 处理
Object current = processor.postProcessAfterInitialization(result, beanName);
// 返回空,则返回 result
if (current == null) {
return result;
}
// 修改 result
result = current;
}
return result;
}
- 对于后置处理器,在实际开发过程中大可以针对此特性设计自己的业务逻辑。
2.1.3 原型模式依赖检查
- Spring 只处理单例模式下得循环依赖,对于原型模式的循环依赖直接抛出异常。主要原因还是在于,和 Spring 解决循环依赖的策略 有关。
- 单例(Singleton)模式, Spring 在创建 Bean 的时候,不等 Bean 创建完成就会将创建 Bean 的
ObjectFactory
提早加入到缓存中,这样一旦下一个 Bean 创建的时候需要依赖 bean 时则直接使用ObjectFactroy
。 - 原型(Prototype)模式,没法使用缓存,所以 Spring 对原型模式的循环依赖处理策略则是 不处理。
- 单例(Singleton)模式, Spring 在创建 Bean 的时候,不等 Bean 创建完成就会将创建 Bean 的
// AbstractBeanFactory.java
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
-
isPrototypeCurrentlyInCreation()
方法,判断当前 Bean 是否正在创建。
// AbstractBeanFactory.java
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) // 相等
|| (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); // 包含
}
/** Names of beans that are currently in creation. */
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");
- 检测逻辑和单例模式一样,一个集合存放着正在创建的 Bean ,从该集合中进行判断即可,只不过单例模式的集合为
Set
,而原型模式的则是ThreadLocal
。
2.1.4 从 parentBeanFactory 获取 Bean
- 如果 beanDefinitionMap 中不存在 beanName 的
BeanDefinition
(即在 Spring bean 初始化过程中没有加载),则尝试从 parentBeanFactory 中加载。
// AbstractBeanFactory.java
// 获取 parentBeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
// parentBeanFactory 不为空且 beanDefinitionMap 中不存该 name 的 BeanDefinition
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 确定原始 beanName
String nameToLookup = originalBeanName(name);
// 若为 AbstractBeanFactory 类型,委托父类处理
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// 委托给构造函数 getBean() 处理
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else {
// 没有 args,委托给标准的 getBean() 处理
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
- 委托 parentBeanFactory 的
getBean()
方法进行处理,在获取之前对 breanName 进行简单的处理,主要是为了获取原始的 beanName 。
// AbstractBeanFactory.java
protected String originalBeanName(String name) {
String beanName = transformedBeanName(name); // 1.
if (name.startsWith(FACTORY_BEAN_PREFIX)) { // 2.
beanName = FACTORY_BEAN_PREFIX + beanName;
}
return beanName;
}
- 方法的调用流程。
- 步骤 1,对 name 进行转换,获取真正的 beanName 。
-
步骤 2,如果 name 是以 " & " 开头的,则加上 " & ",因为在
transformedBeanName()
方法中去掉了,这里 补上。
2.1.5 将指定的 Bean 标记为已经创建或即将创建
- 方法参数 typeCheckOnly,用于判断调用
getBean()
方法时,表示是否为仅仅进行类型检查获取 Bean 对象。- 如果不是仅仅做类型检查,而是创建 Bean 对象,则需要调用
markBeanAsCreated()
方法,进行记录。
- 如果不是仅仅做类型检查,而是创建 Bean 对象,则需要调用
// AbstractBeanFactory.java
/**
* Names of beans that have already been created at least once.
*
* 已创建 Bean 的名字集合
*/
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
protected void markBeanAsCreated(String beanName) {
// 没有创建
if (!this.alreadyCreated.contains(beanName)) {
// 加上全局锁
synchronized (this.mergedBeanDefinitions) {
// 再次检查一次:DCL 双检查模式
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
// 从 mergedBeanDefinitions 中删除 beanName,并在下次访问时重新创建它。
clearMergedBeanDefinition(beanName);
// 添加到已创建 bean 集合中
this.alreadyCreated.add(beanName);
}
}
}
}
protected void clearMergedBeanDefinition(String beanName) {
this.mergedBeanDefinitions.remove(beanName);
}
2.1.6 获取 BeanDefinition
- 因为从 XML 配置文件中读取到的 Bean 信息是存储在
GenericBeanDefinition
中。- 但是,所有的 Bean 后续处理都是针对于
RootBeanDefinition
的,所以这里需要进行一个转换。 - 转换的同时,如果父类 bean 不为空,则一并合并父类的属性。
- 但是,所有的 Bean 后续处理都是针对于
// AbstractBeanFactory.java
// 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
- 调用
getMergedLocalBeanDefinition()
方法,获取相对应的BeanDefinition
对象。
// AbstractBeanFactory.java
/** Map from bean name to merged RootBeanDefinition. */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
// 1. 快速从缓存中获取,如果不为空,则直接返回
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
// 获取 RootBeanDefinition,
// 2. 如果返回的 BeanDefinition 是子类 bean 的话,则合并父类相关属性
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
-
方法的调用流程。
-
步骤 1,直接从 mergedBeanDefinitions 缓存中获取相应的
RootBeanDefinition
对象,如果存在则直接返回。 -
步骤 2,获取
RootBeanDefinition
对象。若获取的BeanDefinition
为子BeanDefinition
,则需要合并父类的相关属性。
-
步骤 1,直接从 mergedBeanDefinitions 缓存中获取相应的
-
调用
checkMergedBeanDefinition()
方法,检查给定的合并的BeanDefinition
对象。
// AbstractBeanFactory.java
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
throws BeanDefinitionStoreException {
if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
}
2.1.7 对依赖 Bean 的处理
- 如果一个 Bean 有依赖 Bean 的话,那么在初始化该 Bean 时需要先初始化它所依赖的 Bean。
// AbstractBeanFactory.java
// Guarantee initialization of beans that the current bean depends on.
// 处理所依赖的 bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 1. 若给定的依赖 bean 已经注册为依赖给定的 bean
// 即循环依赖的情况,抛出 BeanCreationException 异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 2. 缓存依赖调用
registerDependentBean(dep, beanName);
try {
// 3. 递归处理依赖 Bean
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
- 通过迭代的方式依次对依赖 bean 进行检测、校验。如果通过,则调用
getBean()
方法,实例化依赖的 Bean 对象。- 对于依赖的 Bean ,会优先加载,在 Spring 的加载顺序中,在初始化某一个 Bean 的时候,首先会初始化这个 Bean 的依赖。
isDependent
- 调用
isDependent()
方法,校验该依赖是否已经注册给当前 Bean。
// DefaultSingletonBeanRegistry.java
/**
* Map between dependent bean names: bean name to Set of dependent bean names.
*
* 保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合
*/
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
- dependentBeanMap 对象保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合。
- 同步加锁给 dependentBeanMap 对象,然后进行校验。
// DefaultSingletonBeanRegistry.java
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
// alreadySeen 已经检测的依赖 bean
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
// 获取原始 beanName
String canonicalName = canonicalName(beanName);
// 获取当前 beanName 的依赖集合
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
// 存在,则证明存在已经注册的依赖
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
// 递归检测依赖
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
// 添加到 alreadySeen 中
alreadySeen.add(beanName);
// 递推
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
registerDependentBean
- 如果校验成功,则调用
registerDependentBean()
方法,将该依赖进行注册,便于在销毁 Bean 之前对其进行销毁。
// DefaultSingletonBeanRegistry.java
/**
* Map between dependent bean names: bean name to Set of dependent bean names.
*
* 保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合
*/
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.
*
* 保存的是依赖 beanName 之间的映射关系:依赖 beanName - > beanName 的集合
*/
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取 beanName
String canonicalName = canonicalName(beanName);
// 添加 <canonicalName, <dependentBeanName>> 到 dependentBeanMap 中
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
// 添加 <dependentBeanName, <canonicalName>> 到 dependenciesForBeanMap 中
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
- 将该映射关系保存到两个集合中 dependentBeanMap、dependenciesForBeanMap 。
getBean
- 调用
getBean()
方法,实例化依赖 Bean 对象。
2.1.8 对不同作用域的 Bean 进行实例化
- Spring Bean 的作用域默认为 singleton 。还有其他作用域,如 prototype、request、session 等,不同的作用域会有不同的初始化策略。
2.1.8.1 singleton
- Spring 的 scope 默认为 singleton。
- 加载了单例 bean 后,调用
getObjectForBeanInstance()
方法,从 bean 实例中获取对象。
- 加载了单例 bean 后,调用
// AbstractBeanFactory.java
if (mbd.isSingleton()) { // 单例模式
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
// 显式从单例缓存中删除 Bean 实例
// 因为单例模式下为了解决循环依赖,可能他已经存在了,所以销毁它。
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
- 可以从缓存中获取单例模式的 bean。如果缓存中不存在,则需要从头开始加载 Bean ,这个过程由
getSingleton()
方法来实现。
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 全局加锁
synchronized (this.singletonObjects) {
// 1. 从缓存中检查一遍
// 因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
Object singletonObject = this.singletonObjects.get(beanName);
// 为空,开始加载过程
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 2. 加载前置处理
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 3. 初始化 bean
// 这个过程其实是调用 createBean() 方法
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;
}
// 4. 后置处理
afterSingletonCreation(beanName);
}
// 5. 加入缓存中
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
- 这个过程并没有真正创建 Bean 对象,仅仅只是做了一部分准备和预处理步骤,方法的调用流程。
- 步骤 1,再次检查缓存是否已经加载,如果已经加载则直接返回,否则开始加载过程。
-
步骤 2,
beforeSingletonCreation()
方法记录加载单例 bean 之前的加载状态,即前置处理。 -
步骤 3,调用参数传递的
ObjectFactory
的getObject()
方法,实例化 bean。 -
步骤 4,调用
afterSingletonCreation()
方法,进行加载单例后的后置处理。 -
步骤 5,调用
addSingleton()
方法,将结果记录并加入值缓存中,同时删除加载 bean 过程中所记录的一些辅助状态。
addSingleton
// DefaultSingletonBeanRegistry.java
/**
* Cache of singleton objects: bean name to bean instance.
*
* 存放的是单例 bean 的映射。
*
* 对应关系为 bean name --> bean instance
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* Cache of singleton factories: bean name to ObjectFactory.
*
* 存放的是【早期】的单例 bean 的映射。
*
* 对应关系也是 bean name --> bean instance。
*
* 它与 {@link #singletonObjects} 的区别区别在,于 earlySingletonObjects 中存放的 bean 不一定是完整的。
*
* 从 {@link #getSingleton(String)} 方法中,中我们可以了解,bean 在创建过程中就已经加入到 earlySingletonObjects 中了,
* 所以当在 bean 的创建过程中就可以通过 getBean() 方法获取。
* 这个 Map 也是解决【循环依赖】的关键所在。
**/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/**
* Cache of early singleton objects: bean name to bean instance.
*
* 存放的是 ObjectFactory 的映射,可以理解为创建单例 bean 的 factory 。
*
* 对应关系是 bean name --> ObjectFactory
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
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);
}
}
操作 | 说明 |
---|---|
put | singletonObjects 属性,单例 bean 的缓存。 |
remove | singletonFactories 属性,单例 bean Factory 的缓存。 |
remove | earlySingletonObjects 属性,“早期”创建的单例 bean 的缓存。 |
add | registeredSingletons 属性,已经注册的单例缓存。 |
2.1.8.2 原型模式
// AbstractBeanFactory.java
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
// 1. 加载前置处理
beforePrototypeCreation(beanName);
// 2. 创建 Bean 对象
prototypeInstance = createBean(beanName, mbd, args);
} finally {
// 3. 加载后缀处理
afterPrototypeCreation(beanName);
}
// 4. 从 Bean 实例中获取对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
- 原型模式的初始化过程,直接创建一个新的 Bean 的实例,方法的调用流程。
- 调用
beforePrototypeCreation()
方法,记录加载原型模式 bean 之前的加载状态,即前置处理。 - 调用
createBean()
方法,创建一个 bean 实例对象。 - 调用
afterSingletonCreation()
方法,进行加载原型模式 bean 后的后置处理。 - 加载了单例 bean 后,调用
getObjectForBeanInstance()
方法,从 bean 实例中获取对象。
- 调用
beforePrototypeCreation
// AbstractBeanFactory.java
/** Names of beans that are currently in creation. */
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) { // String
this.prototypesCurrentlyInCreation.set(beanName);
} else if (curVal instanceof String) { // String => Set
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
} else { // Set
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
afterSingletonCreation
// AbstractBeanFactory.java
protected void afterPrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal instanceof String) { // String => null
this.prototypesCurrentlyInCreation.remove();
} else if (curVal instanceof Set) { // Set
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.remove(beanName);
if (beanNameSet.isEmpty()) { // Set => null
this.prototypesCurrentlyInCreation.remove();
}
}
}
2.1.8.3 其它作用域
- 核心流程和原型模式一样,只是获取 bean 实例由
Scope#get()
方法实现。
// AbstractBeanFactory.java
else {
// 获得 scopeName 对应的 Scope 对象
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 {
// 从指定的 scope 下创建 bean
Object scopedInstance = scope.get(beanName, () -> {
// 加载前置处理
beforePrototypeCreation(beanName);
try {
// 创建 Bean 对象
return createBean(beanName, mbd, args);
} finally {
// 加载后缀处理
afterPrototypeCreation(beanName);
}
});
// 从 Bean 实例中获取对象
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);
}
}
- org.springframework.beans.factory.config.Scope 接口,有多种实现类。
// SimpleThreadScope.java
private final ThreadLocal<Map<String, Object>> threadScope =
new NamedThreadLocal<Map<String, Object>>("SimpleThreadScope") {
@Override
protected Map<String, Object> initialValue() {
return new HashMap<>();
}
};
@Override
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;
}
2.1.9 类型转换
- 在调用
doGetBean()
方法时,有一个 requiredType 参数。该参数的功能是将返回的 Bean 转换为 requiredType 类型,一般而言,是不需要进行类型转换的,requiredType 为空(比如getBean(String name)
方法)。
// AbstractBeanFactory.java
// 检查需要的类型是否符合 bean 的实际类型
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 执行转换
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
// 转换失败,抛出 BeanNotOfRequiredTypeException 异常
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());
}
}
2.1.10 小结
- Spring Bean 加载过程可以拆分分为三个部分。
- 从缓存中获取单例 Bean ,以及对 Bean 的实例中获取对象。
- 从单例缓存中获取 Bean ,Bean 加载,以及 Bean 的依赖处理。
- Bean 已经加载,依赖也处理完毕,则进行各个作用域的 Bean 初始化过程。
网友评论