Spring源码解析(七)-获取单例bean
Spring版本
5.2.5.RELEASE
参考
源码解析
1. BeanFactory#getBean(String name)
应用初始化容器的时候,bean并不会马上被加载(除非显式指定lazyinit = false
),而是在调用getBean
的时候才会被加载,下面我们就来看看getBean
的具体实现
getBean
方法实际上是交由doGetBean
实现的:
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
查看doGetBean
方法:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 已注册的bean会以<beanName,bean>的形式缓存在一个map
// 1、由于BeanFactory本身也是一个bean,当请求是BeanFactory这个bean的时候,name是带有&符号的,而缓存map里面的beanName都是不带&符号的
// 2、name也有可能是bean的一个别名
// transformedBeanName方法便是将以上俩种可能的name转化为具体的beanName
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 从缓存map中获取bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 这里面对sharedInstance做了一些处理,分为以下几种情况:
// 1、如果name是以&符号开头(代表想要获取的是FactoryBean),
// 但是sharedInstance是NullBean,或者sharedInstance根本不是一个FactoryBean,
// 那么此时返回一个NullBean,或者抛出异常
// 2、如果sharedInstance是一个普通bean,或者name是以&开头,代表想要获取FactoryBean本身,此时直接返回
// 3、其他情况下,调用getObject方法获取真正的bean实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// BeanFactory 无法处理Prototype类型的bean的循环依赖问题
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 获取父BeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
// 父BeanFactory不为空且<beanName,beanDefinition>的map中不含有该beanName(也就是说该bean对应的BeanDefinition还未进行解析),那么将获取bean实例委托给父BeanFactory
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 将可能是别名的name解析成具体的beanName,如果name以&开头,那么返回值也将带有&符号
String nameToLookup = originalBeanName(name);
// 如果是AbstractBeanFactory类型,递归调用doGetBean方法
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
// 如果参数不为空,调用接口层次的getBean,由getBean决定具体的实现方法
// (getBean是一个通用接口声明,具体有多中实现,包含但不止AbstractBeanFactory)
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
// 参数为空,与参数不为空逻辑一致,只不过交由getBean的另外一个重载方法去处理
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// typeCheckOnly
// true表示doGetBean仅仅是为了做类型检查
// false表示为了实际使用bean实例,如果是实际使用bean实例,则有必要标识为已创建,以让缓存起到作用
if (!typeCheckOnly) {
// 将beanName加入到alreadyCreated集合中,标识为已创建,并且将beanDefinition的stale属性设置为true,防止创建期间元数据发生变更
markBeanAsCreated(beanName);
}
try {
// 将父bean和子bean合并,可能是从缓存中获取
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查mbd是否是抽象,若是,抛出异常
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 保证bean下的depends on已经实例化
// 注意depends on和循环依赖的区别
// <bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
// <property name="manager" ref="manager" />
// </bean>
// 使用@Autowired的时候,我们注入的是property
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 不允许循环depends on
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册depends on关系,注册之后其他bean创建的时候才能通过isDependent方法检查循环depends on
registerDependentBean(dep, beanName);
try {
// 创建depend on实例
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
// 创建单例类型的bean实例
// getSingleton方法后面解析
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.
// 在早期的创建过程中,可能为了解决循环引用问题,导致beanName加入了singleton缓存中,此时需要移除该缓存
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
// 创建prototype类型的bean实例
Object prototypeInstance = null;
try {
// 写入prototype类型的依赖关系,以便上述的isPrototypeCurrentlyInCreation方法做出拦截
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 创建完毕则可以删除prototype类型的依赖关系
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 创建其他类型的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;
}
}
// Check if required type matches the type of the actual bean instance.
// 检查创建出来的bean实例是否是要求的类型
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.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
方法很长,总结起来主要做了以下几点:
- 通过
transformedBeanName
做了beanName的转换 - 从缓存中获取bean实例
- 缓存不为空,通过
getObjectForBeanInstance
获取bean实例 - 缓存为空,创建bean
- 缓存不为空,通过
- 将获取到的bean实例与
requiredType
做校验,必要时进行类型转换
下面逐个解析
2. 转换beanName
方法一开始传进来的beanName可能有以下俩种情况:
- 以&开头的name,代表获取FactoryBean这个bean
- 别名
而<beanName,bean>的缓存中,beanName是不带&符号的非别名beanName,这时候需要将beanName转化为真正的beanName,方便后面再缓存中获取beanName对应的bean:
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
通过别名获取到真正的beanName:
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
对name做去除&符号的处理:
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// 如果name不是以&开头,直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 否则,从transformedBeanNameCache中获取name对应的value,如果value为空,对beanName剔除&前缀,之后写入transformedBeanNameCache
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
其中,Map#computeIfAbsent定义如下:
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
含义是如果map中的key对应的value为空,那么使用mappingFunction生产一个值,作为value,并写入map中
3. AbstractBeanFactory#getSingleton
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从缓存中读取beanName对应的bean
Object singletonObject = this.singletonObjects.get(beanName);
// 如果不存在该beanName对应的bean,并且该bean处于创建之中(由于循环依赖导致beanName被写入singletonsCurrentlyInCreation),那么通过早期引用来解决循环依赖问题
// 写入singletonsCurrentlyInCreation这一步发生在AbstractBeanFactory#doGetBean#createBean#doCreateBean#populateBean#applyPropertyValues
// #resolveValueIfNecessary#resolveInnerBean#getObjectFromFactoryBean#beforeSingletonCreation
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从早期引用中获取bean
singletonObject = this.earlySingletonObjects.get(beanName);
// 早期引用不存在bean且允许使用早期引用
if (singletonObject == null && allowEarlyReference) {
// 获取bean创建工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用getObject方法创建bean
singletonObject = singletonFactory.getObject();
// 写入早期引用,解决循环依赖问题
this.earlySingletonObjects.put(beanName, singletonObject);
// 移除工厂
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
从缓存中获取bean,这里涉及到了循环依赖的处理,大致就是如果碰到当前获取的bean处于正在创建中:
isSingletonCurrentlyInCreation
那么说明当前bean已经处于循环依赖中,那么写入earlySingletonObjects
中,那么下次进来,就可以直接返回对应实例,从而解决早期引用问题。
举例来说,A依赖B,B依赖A,首先创建A,将A写入正在创建的bean集合
isSingletonCurrentlyInCreation
中,然后发现依赖B,接着去创建B,发现依赖A,这时发现A处于isSingletonCurrentlyInCreation
中,那么将A写入早期引用集合earlySingletonObjects
中,然后完成创建B流程,接着也就完成创建A流程
4. AbstractBeanFactory#getObjectForBeanInstance
查看源码之前,有个疑问,既然已经从缓存中获取到了实例,如果还要通过
getObjectForBeanInstance
进行处理?这是因为从缓存中获取到实例是最原始的实例,如果通过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.
// 如果name以&开头
if (BeanFactoryUtils.isFactoryDereference(name)) {
// NullBean类型直接返回
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 以&开头代表想要获取FactoryBean实例,但得到的实例实际上不是FactoryBean实例,抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// 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.
// 普通类型bean实例,直接返回该实例
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 如果上述均不满足,调用BeanFactory工厂getObject方法创建bean
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 从factoryBeanObjectCache缓存中获取缓存
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
// 合并BeanDefinition
mbd = getMergedLocalBeanDefinition(beanName);
}
// synthetic字面意思是合成的,true代表非应用本身创建的bean,如使用<aop:config>创建的自动代理bean
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 继续调用getObjectFromFactoryBean方法创建bean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
可以分成三个部分查看流程:
- 首先处理name以&开头的情况,如果是
NullBean
,直接返回实例beanInstance
;如果对应实例beanInstance
不是FactoryBean
类型,抛出异常;否则,返回实例beanInstance
- 如果是普通bean,直接返回对应实例
- 如果是其他情况,通过
getObjectFromFactoryBean
获得bean实例
5. AbstractBeanFactory#getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 单例模式,有使用缓存
// containsSingleton方法判断了singletonObjects是否包含beanName,而singletonObjects在doGetBean中sharedInstance为空的分支中,通过getSingleton方法进行了put
// 而这一步是sharedInstance不为空的分支走进来的,所以这时候singletonObjects应该是已经包含beanName了
if (factory.isSingleton() && containsSingleton(beanName)) {
// getSingletonMutex返回singletonObjects对象,单例模式在并发情况下需要保证只创建一个实例,所以需要对singletonObjects加锁
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// doGetObjectFromFactoryBean调用了getObject方法
object = doGetObjectFromFactoryBean(factory, beanName);
// 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)
// TODO
// 没看懂这几句代码
// 貌似是上述的getObject方法调用期间,只会在不存在实例的情况下才创建实例并保存,所以这里要再次获取一次,保证获取的是第一次创建的实例
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
// 进入这个分支意味着object是第一次创建的实例,这时候需要通过shouldPostProcess判断是否进行后置处理
// PostProcess中文含义便是"后处理"
if (shouldPostProcess) {
// TODO
// 不是很懂这里判断的含义
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 将beanName加入singletonsCurrentlyInCreation
beforeSingletonCreation(beanName);
try {
// 应用后置处理方法
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
// 将beanName从singletonsCurrentlyInCreation移除
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
// 已创建的实例写入缓存
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// 原型模式,不使用缓存,每次重新创建
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
该段代码主要是做了一些后置处理,核心在于doGetObjectFromFactoryBean
6. AbstractBeanFactory#doGetObjectFromFactoryBean
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
// 安全方面的处理
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 调用getObject方法创建实例
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;
}
7. AbstractBeanFactory#getMergedLocalBeanDefinition
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
// 查阅缓存
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
// getBeanDefinition(beanName):从beanDefinitionMap获取BeanDefinition
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
// <bean id="hello" class="xyz.coolblog.innerbean.Hello">
// <property name="content" value="hello"/>
// </bean>
//
// <bean id="hello-child" parent="hello">
// <property name="content" value="I`m hello-child"/>
// </bean>
// spring支持通过以上方式进行配置继承,子类从而可以覆盖或者继承父类的配置
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);
}
// stale:陈旧,该属性用于标示是否需要进行重新合并
if (mbd == null || mbd.stale) {
previous = mbd;
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 {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
// 子beanName和父beanName不同的情况下
// 递归调用,获取parentBeanDefinition
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
// 子beanName和父beanName相同的情况下
// TODO 没看懂
// 看起来也是一个递归调用,但是只在parent是ConfigurableBeanFactory的情况下进行递归调用
// 递归后最终还是得回到这个方法,并且此时并非是ConfigurableBeanFactory类型(也就是不再进入这个分支)
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.
// 没配置的情况下设置默认singleton scope
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
// 容器是非singleton并且bean是singleton的情况下,bean不可能是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) {
// 重新合并,使用previous的配置覆盖mbd的配置
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
主要逻辑就是对BeanDefinition整合一下parentBeanDefinition,对于BeanDefnition,可以戳《Spring源码解析(一)-BeanDefinition加载》
总结
画个流程图理清一下doGetBean的流程
本文仅讲述了获取单例bean的流程,流程图中createBean等源码的解析放置于下一章节《Spring源码解析(八)-创建单例bean》