doGetBean的总体流程
- 尝试从缓存中获取Bean.
- 判断是否有循环依赖.
- 判断能否从当前容器获取Bean,不能则递归从父容器中获取.
- 合并BeanDefiniton,并检查BeanDefiniton,作为createBean的材料.
- 根据声明的DependsOn去实例化需要提前实例化的Bean.
- 根据不同的Scope:single、prototype、其他scope使用不同的创建Bean策略.
- 对Bean做类型检查.
1. 尝试从缓存中获取Bean
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 返回Bean名称,必要时去除工厂取消引用前缀,并将别名解析为规范名称
// 通过三种形式获取beanName.
// 1. 原始的beanName.2. FactoryBean->&beanName. 3. alias
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 尝试从单例缓存集合中获取bean实例
Object sharedInstance = getSingleton(beanName);
// 省略....
}
要从缓存中获取Bean,首先要转换出真正的beanName.
我们注册在Spring中的Bean,其名称有三种形式:
- beanName.即Bean本身持有的名称,如UserDao这个Bean,Spring会自动为其生成"userDao".
- alias.别名,如果你想指定Bean的名称,可以在@Bean中指定该Bean的别名.示例:
@Bean({"personC", "Kobe"})
- FactoryBean.容器工厂的Bean,对这类Bean会返回其实现类中的
getObject
对象.名称通常为"&beanName".
Spring通过transformedBeanName来转换出beanName:
如果是beanName,返回beanName.
如果是别名,返回beanName.
如果是FactoryBean,并且传入的beanName以("&beanName")的形式,返回beanName.
当获取到beanName后,Spring尝试从缓存中获取bean实例.
- DefaultSingletonBeanRegistry#getSingleton
@Override
@Nullable
public Object getSingleton(String beanName) {
// 第二个参数为是否允许立即加载,这里传入的是true
return getSingleton(beanName, true);
}
2. Spring的三级缓存
- singletonObjects: 存储完整的Bean.
- earlySingletonObjects: 半成品的Bean,未进行属性赋值.
- singletonFactories: 提前暴露的对象实例,仅仅做了实例化,未具备属性.
/** Cache of singleton objects: bean name to bean instance. */
/** 一级缓存:单例对象缓存池,beanName->Bean,其中存储的是完整的Bean.*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory.<br>
* 三级缓存:单例工厂的缓存,beanName->ObjectFactory,添加进去的时候实例未具备属性.<br>
* 用于保存beanName和创建Bean工厂之间的关系map,单例Bean在创建之初过早暴露出去的Factory.<br>
* 为什么采用工厂方法,是因为有些Bean是需要被代理的,总不能把代理前的暴露出去那就毫无意义了.<br>
* */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance.<br>
* 早期的单例对象,beanName->ObjectFactory,存储的是实例化后,属性未赋值的单例对象.<br>
* 执行了工厂方法生产出来的bean被放进去之后.<br>
* 那么当bean在创建过程中,就可以通过getBean方法获取到.<br>
* */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
3.从三级缓存中获取对象实例
- DefaultSingletonBeanRegistry#getSingleton
/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).<br>
* 返回以给定名称注册的(原始)单例对象。<br>
* 检查已经实例化的单例,并且还允许对当前创建的单例的早期引用(解析循环引用)。<br>
* 单例对象只能存在三级缓存中的某一级,此处会尝试从一级、二级、三级中进行获取.<br>
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 尝试从一级缓存中获取完整的Bean
Object singletonObject = this.singletonObjects.get(beanName);
// 如果完整的单例Bean没有被创建出来,创建中的Bean的名字会被保存在singletonsCurrentlyInCreation中
// 也就是说,当前所需要获取的bean是否是singleton的,并且处于创建中的形态
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 同步锁,开始对缓存对象进行操作.
// 这里作为锁还有一个原因是二级缓存和三级缓存都是HashMap,需要一个锁来控制这两个map的操作
synchronized (this.singletonObjects) {
// 尝试从二级缓存earlySingletonObjects中获取半成品的Bean。
// 二级缓存存储的是未对属性进行添加的Bean.
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果还获取不到,并且allowEarlyReference为true,则表示可以进行循环引用
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存singletonFactories这个ObjectFactory实例的缓存中尝试获取创建此Bean的单例工厂实例
// ObjectFactory为用户定制(容器中的代理Bean),FactoryBean框架会进行特殊处理(自定义)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用单例工厂的getObject方法获取对象实例
singletonObject = singletonFactory.getObject();
// 将实例放入二级缓存中.
this.earlySingletonObjects.put(beanName, singletonObject);
// 从三级缓存中删除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
Spring默认支持循环依赖,在这个getSingleton()中,根据beanName去一级、二级、三级缓存中进行查找:
- 尝试从一级缓存中查找完整的Bean实例,找到则直接返回.
- 如果无法从一级缓存中查找,对一级缓存进行上锁,然后尝试从二级缓存中查找半成品的Bean.找到直接返回.
- 从三级缓存中查找,找到则放入二级缓存,同时为了保证一个对象实例为单例,将该实例从第三级缓存中进行移除.
4. 检测循环依赖.
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 省略若干代码....
// 尝试从单例缓存集合中获取bean实例
Object sharedInstance = getSingleton(beanName);
// 如果之前已经创建过该单例bean,并且args为空(单例 bean不可以用这个args,它是为多例设计的)
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
// 如果Bean还在创建中,则说明是循环依赖.
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 + "'");
}
}
// 如果是普通的bean,直接返回,如果是factoryBean,则返回它的getObject.
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 省略若干代码....
}
尝试从缓存中获取对象实例后,如果该共享对象实例不为空且参数为空,那么进行循环依赖的检测:
1.如果该beanName出现在singletonsCurrentlyInCreation
中,那么证明是循环依赖.
2.否则为缓存的Bean实例.
通过getObjectForBeanInstance
返回对象实例.该方法会判断bean是否为FactoryBean
,则通过其getObject
获取Bean实例:
在访问FactoryBean的过程中,先从FactoryBean缓存中获取(单例模式下,仅存在一个FactoryBean),如果没有则调用其getObject
方法,此处Spring使用了双重检测锁机制来创建FactoryBean.值得一读.
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
// 上同步锁
synchronized (getSingletonMutex()) {
// 双重检测锁机制,先从缓存中获取,多线程下可能别的线程已完成该单例Bean的创建.
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 调用getObject工厂方法创建Bean实例
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)
// 如果在getObject期间别的线程异步进行了bean的创建,那么使用更早的版本,以保证单例
// 为什么出现两次从缓存读取的操作,因为用户自定义的getObject可能会出现异步,所以这里需要再进行一次判断
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
// Spring的内部类不会进入到这个方法,因为Spring不允许第三方框架通过后置处理器更改其内部类
if (shouldPostProcess) {
// 该Bean实例是否有别的线程在尝试创建,但是未进行后置处理
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 后置处理完成前,先加入缓存中锁定起来
beforeSingletonCreation(beanName);
try {
// 触发BeanPostProcessor.第三方框架可以使用AOP来包装Bean实例
// 对Bean实施创建上的后置处理
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
// 锁定解除
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
// 放入缓存中,证明单例已经创建完成了.
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// 非单例直接getObject
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;
}
}
5.如果从缓存中获取不到Bean实例,开始着手创建Bean.
// 如果scope->prototype,singleton.但是在缓存中无法找到
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 如果scope为prototype并且仍然处于创建的状态,那么可以认为是处于循环依赖中了.
// 针对prototype的循环依赖,spring无法解决,此处会抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果在当前容器中无法找到指定名称的bean,此时递归去parentFactory查找.
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 针对FactoryBean,将Bean的&重新拼上
String nameToLookup = originalBeanName(name);
// 如果parentBeanFactory属于AbstractBeanFactory实例
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.
// 如果没有参数,委托父级容器根据指定名称和type进行查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
// 委派父级容器根据指定名称查找.
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
// 如果不是仅仅做类型检测则创建bean
markBeanAsCreated(beanName);
}
try {
// 将父类的BeanDefinition与子类的BeanDefinition进行合并覆盖
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 对合并的BeanDefiniton进行检测,主要判断是否为abstract.
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 获取当前Bean所有依赖的Bean名称
String[] dependsOn = mbd.getDependsOn();
// 如果当前Bean设置了dependsOn的属性(用来指定Bean初始化即销毁时的顺序)
// <bean id = A ,Class = "xxx.xxx.A" depends-on = "B">
// <bean id = B ,Class = "xxx.xxx.B">
if (dependsOn != null) {
for (String dep : dependsOn) {
// 检测该依赖是否已经注册给当前Bean
// A-dependsOn-B
// B-dependsOn-A
// 如果是这种情况,直接抛出异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 缓存依赖调用,dep->被依赖的beanName
registerDependentBean(dep, beanName);
try {
// 递归调用getBean,注册Bean之间的依赖(C->B->A)
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 如果BeanDefiniton为单例
if (mbd.isSingleton()) {
// 匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
// 关键方法:单例类实例化的入口
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建单例bean的入口.
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之前,Spring会先检查当前
beanName
是否在prototypesCurrentlyInCreation
中,prototypesCurrentlyInCreation
是一个ThreadLocal的Set集合,其中存储了当前正在创建的多例BeanName集合,Spring不支持prototye
作用域的循环依赖,所以会抛出一个BeanCurrentlyInCreationException
.- 向上递归获取父容器,尝试找到该beanName的对象实例.这里有点像类加载时的双亲委派机制去加载bean.
- 检查是否为类型检查,如果不仅仅是类型检查,那么Spring知晓为创建Bean了,会开始在一个
alreadyCreated
的Set集合中加入该BeanName的名称.这里会存储已经创建好的或者正在创建中的beanName.并且进行clearMergedBeanDefinition
操作。- 如果从父容器无法获取,开始进行进行创建Bean之前的一些准备工作,例如
getMergedLocalBeanDefinition
,检测当前的RootBeanDefinition
是否为abstract
的.同时,如果bean声明了dependsOn
,还会进行相应的注册逻辑,同时递归调用getBean
方法进行Bean的初始化.
注意:dependsOn
是不可以有循环声明的.因为dependsOn
显示声明了Bean创建的顺序,如果还存在循环声明,就会乱套.- 经过上面的校验后,如果Bean的作用域为
singleton
,就开始进行createBean
操作了.此处Spring是调用了一个重载的getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法.而createBean
作为ObjectFactory
这个函数式接口的代码块进行了传递.在这个getSingleton
中,Spring会调用传进来的singletonFactory.getObject()方法
,实际上,就是调用的createBean
.
- DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 上同步锁
synchronized (this.singletonObjects) {
// 从一级缓存中获取Bean实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 如果当前容器正在当前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 + "'");
}
// 查看当前bean是否可以进行加载
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 传入的lambda代码块逻辑在这里执行.
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;
}
// 从singletonsCurrentlyInCreation中移除当前beanName的信息,因为已经完成了bean的创建了
afterSingletonCreation(beanName);
}
// 如果创建了一个新的单例Bean,将其添加到一级缓存中.
// 同时为了保证一个单例Bean只出现一次,将其从二级、三级缓存中进行移除
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
- 如果当前bean的scope为
prototype
,直接进行createBean,原型模式下,每次getBean
都会创建新的对象实例.
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
// 如果是原型模式,创建一个实例,在原型模式下,每次getBean都会产生一个新的实例
Object prototypeInstance = null;
try {
// 将当前创建的Bean标记为创建中
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 完成创建后,从prototypesCurrentlyInCreation移除beanName
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
7.如果bean的scope不是
singleton
和prototype
,则调用scope.get()
来选择合适的加载策略.
8.做类型校验,这里不做重点的阐述.
网友评论