Spring 单例创建流程
Posted 看写写
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 单例创建流程相关的知识,希望对你有一定的参考价值。
所有的代码,都只保留了主干流程,为了阅读方便进行了简化处理,具体以源码为准
这里仅供参考
org.springframework.beans.factory.support.AbstractBeanFactory
单例整体流程
// 通过工厂类,获取对象都是通过这个方法获取的
@Override
public Object getBean(String name) throws BeansException
return doGetBean(name, null, null, false);
// 删除了不相干的代理,只保留主干
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException
// Eagerly check singleton cache for manually registered singletons.
// 第一次检查, 从缓存里面取,如果已经存在直接返回, 这里可以
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null)
return;
// Create bean instance. 创建单例
if (mbd.isSingleton())
sharedInstance = getSingleton(beanName,
// 使用工厂方法的好处
// 1, 解偶,创建和使用解偶,使用的地方不需要知道具体的细节
// 2, 可以根据需要再生成对象,懒生成,而不是每次都生成对象,加快spring启动的速度
new ObjectFactory<Object>()
@Override
public Object getObject() throws BeansException
try
// 具体创建单例的地方,这例使用就是下面讲解的AbstractAutowireCapableBeanFactory类
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.
destroySingleton(beanName);
throw ex;
);
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
return (T) bean;
// 整体的流程控制,保证单例的特性,防止重复生成对象
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)
Assert.notNull(beanName, "'beanName' must not be null");
// 加锁,二次检查
synchronized (this.singletonObjects)
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!)");
// 这个地方很重要,保证了单例的特性,防止重复创建对象
beforeSingletonCreation(beanName);
// 创建对象
singletonObject = singletonFactory.getObject();
// 缓存对象
addSingleton(beanName, singletonObject);
return (singletonObject != NULL_OBJECT ? singletonObject : null);
// 判断一个单例是否在创建中
public boolean isSingletonCurrentlyInCreation(String beanName)
return this.singletonsCurrentlyInCreation.contains(beanName);
// 把单例对象的名称,加入到singletonsCurrentlyInCreation, 同步map]中
// 1, 为了后续的判断是否正在创建单例,
// 2, 防止重复创建对象,破换单例的特性
protected void beforeSingletonCreation(String beanName)
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName))
throw new BeanCurrentlyInCreationException(beanName);
创建单例的细节
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory. doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton())
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
if (instanceWrapper == null)
// 根据构造函数创建对象,如果构造函数有参数,会进行参数的解析,填充
instanceWrapper = createBeanInstance(beanName, mbd, args);
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock)
if (!mbd.postProcessed)
try
// mbd合并
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.
// 单利创建的时候,会先把beanName添加到一个map里面,+ lock,保证单例的特性
// 只要是单例 所以这里返回true: isSingletonCurrentlyInCreation(beanName)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// 为了解决循环依赖,单例对象第一次创建完成,会提前发布出去,
// 使用factory原因的可以进行延迟 生成代理对象
// 因为循环依赖属于小概率事件,所以注册一个factory,当真的存在循环依赖的时候
// 再生成真正的对象(spring AOP机制会在这里生成代理对象比较耗时),个人理解所以懒处理的形式,加快速度
if (earlySingletonExposure)
if (logger.isDebugEnabled())
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
addSingletonFactory(beanName, new ObjectFactory<Object>()
@Override
public Object getObject() throws BeansException
// Srping AOP在这里进行增强,提前生成代理对象
return getEarlyBeanReference(beanName, mbd, bean);
);
// Initialize the bean instance.
Object exposedObject = bean;
try
// 填充参数, @Resource, @Autowired 都是在这里进行处理
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null)
// 初始化对象
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);
// 如果提前发布了对象
if (earlySingletonExposure)
// 如果提前发布了对象,但是进行了Spring AOP增强,生成了新的对象,这里需要获取最新的对象,
// 注意这里的参数是false,不能生成新的对象,只能从缓存里面取
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null)
if (exposedObject == bean)
// 体会为最新生成的对象比如 spring AOP代理对象,保证其单例特性,
// 如果这里不进行处理会导致循环依赖的对象和当前的对象不一致,破换了单例的特性
exposedObject = earlySingletonReference;
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName))
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans)
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean))
actualDependentBeans.add(dependentBean);
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
registerDisposableBeanIfNecessary(beanName, bean, mbd);
catch (BeanDefinitionValidationException ex)
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
return exposedObject;
```
## Spring AOP如何解决,循环依赖的问题,同时保证单例特性
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
类是AOP增强的主流程入口
```bash
// spring 解决单例循环依赖的时候,会提前注册一个BeanFactory,这里会提前生成代理类
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 写入这个map的原因,是为了保证单例,这里提前生成了代理类(因为循环依赖),
// A->B->A , 这种情况下,在创建B的时候,会调用这里提前生成A的代理类,
// 这个时候B里面的对A的引用已经是新的代理类了,但是A本身的还在初始化的过程中还没完成
// 需要完成A的初始化,但是还不能重新生成新的代理类否则就不是单例了,所以这里记录
// 在postProcessAfterInitialization的时候,对比引用,如果一样,就不重新生成代理类了
// 同时这个方法只会被调用一次,因为单例对象生成过成中会加锁,而且进行缓存,保证创建完成之后
// 只会从缓存里面取。同时最终A初始化完成之后,会把最终返回的引用对象体会为这里生成的代理对象,保证单例
this.earlyProxyReferences.put(cacheKey, bean);
// 生成代理类的具体实现
return wrapIfNecessary(bean, beanName, cacheKey);
// 正常的非循环依赖的对象,都从这里进行AOP的增强
// 这里的循环依赖指的是单例循环依赖(非构造函数依赖)
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
if (bean != null)
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 1, 如果是循环依赖则remove返回的bean ,和 当前是bean地址一样,这里是false,直接结束
// 2, 非循环依赖,那这里remove返回的是null,而bean不为空是先决条件,所以这里返回 true,进行类的增强,生成代理类
if (this.earlyProxyReferences.remove(cacheKey) != bean)
// 生成代理类的具体实现
return wrapIfNecessary(bean, beanName, cacheKey);
return bean;
以上是关于Spring 单例创建流程的主要内容,如果未能解决你的问题,请参考以下文章