目录
二、全流程梳理
2.5 获取Bean
- 事实上,bean的生命周期分析(一)中的refresh方法帮我们创建好了BeanFactory,具体创建bean是另外的流程。
- 为什么先讲获取。因为spring源码中是先从ioc容器中获取对象,获取不到再创建的。所以这里先从DefaultListableBeanFactory的doGetBean方法入手,它会委派给它的父类来处理,也就是AbstractBeanFactory。
2.5.1 AbstractBeanFactory类
- 入口是getBean方法
- 下面这个doGetBean是重点,关键部分用注释的形式标记了,下面会针对重点内容进行讲解。
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 重点解析1 getSingleton 详见2.5.2
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 + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 如果我们已经在创建这个bean实例,则失败: 我们假设在循环引用中。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 检查一下bean的定义是否已经存在于工厂中了,这里所谓的bean的定义就是beanDefinition,和之前的串起来了。
BeanFactory parentBeanFactory = getParentBeanFactory();
// 一般不会来这里
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 到这里 beanfactory中是存在beanDefinition的。
// 合并父 BeanDefinition 与子 BeanDefinition 重点解析 详见2.5.3
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 获取DependsOn
String[] dependsOn = mbd.getDependsOn();
// 有依赖的,要先初始化依赖的
if (dependsOn != null) {
for (String dep : dependsOn) {
// 循环依赖
/*
* 检测是否存在 depends-on 循环依赖,若存在则抛异常。比如 A 依赖 B,
* B 又依赖 A,他们的配置如下:
* <bean id="beanA" class="BeanA" depends-on="beanB">
* <bean id="beanB" class="BeanB" depends-on="beanA">
*
* beanA 要求 beanB 在其之前被创建,但 beanB 又要求 beanA 先于它
* 创建。这个时候形成了循环,对于 depends-on 循环,Spring 会直接
* 抛出异常
*/
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 很好理解,既然你要创建的bean依赖其他bean,那就先把其他bean创建好
// 注册依赖Bean
registerDependentBean(dep, beanName);
// 先获取依赖的Bean
getBean(dep);
}
}
// 一切就绪,终于可以来创建bean了。
// Create bean instance.
if (mbd.isSingleton()) {
// 这里是个回调函数,先进入看getSingleton方法,这个和2.5.2里的getSingleton不是一个函数,但内容差不太多,详见2.5.4
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
// 重点解析 4 见2.6.1
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);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
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 '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
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.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
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;
}
2.5.2 重点解析1 getSingleton
涉及三级缓存。检查单例缓存是否有手动注册的单例,这里涉及到三级缓存。
singletonObjects:单例对象的缓存。成熟的对象。
earlySingletonObjects:早期单例对象的缓存。尚未成熟。
singletonFactories:单例工厂的缓存。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 取单例,取到成熟的对象最好了,直接返回
Object singletonObject = this.singletonObjects.get(beanName);
// 没取到 且 正在创建
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) {
// 去单例工厂。未取到返回null
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// 取到单例工厂
if (singletonFactory != null) {
// 创建一个单例对象
singletonObject = singletonFactory.getObject();
// 放入早期单例对象
this.earlySingletonObjects.put(beanName, singletonObject);
// 从工厂中移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
// 有4中情况的返回 单例对象、早期单例对象、单例工厂、null
return singletonObject;
}
很显然,第一次创建bean时这里是取不到的,返回null。回到doGetBean主函数,我们继续往下看。
2.5.3 重点解析2 getMergedLocalBeanDefinition
这个函数是解决下面场景的:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName">
<bean id="parentBean" class="com.test.merge.ParentObject">
<property name="score" value="1200"></property>
</bean>
<bean id="child" paren="parentBean" class="com.test.merge.ComplexObject">
<property name="sex" value="1"></property>
<property name="name" value="11221"></property>
</bean>
</beans>
parent 这个属性有两个功能:
- child 这个 bean 能够获取 parentBean 所定义的属性值。这个前提是 child 这个 bean 必须要拥有这些属性,不管是 child 自己有这个属性,还是从其父类中继承过来的属性。其实说到底还是 child 自己必须要有这个属性,因为从父类继承过来也是在解析过程中将父类的属性设置到子类的 BeanDefinition 中。如果 child 中属性的赋值跟 parentBean 中属性的赋值冲突的情况下,child 中的赋值会覆盖 parentBean 中的赋值。
- child 不存在 class 这个属性时,可以使用 parentBean 的 class。
parent 这个属性跟 bean 的继承没有关系。这个属性的存在是为了方便多个 bean 存在相同的属性时,可以共用同一个 parent,跟 bean 的继承有相似的作用,但它俩不是一个东西。这点大家要注意下。
getMergedLocalBeanDefinition 其实就是来处理 parent 这个属性的。当然其下层的 getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) 的这个方法不仅仅是处理 parent 属性。其实其还需要处理 containingBd 这个属性的,这个我们后续解释。
这个方法的目的就是将 parent 这个属性对应的 bean 定义中的信息设置到 child 中去。
这个方法的代码不是特别复杂,大家在了解了其用途之后可以自行下去看下。这里简单分析一下。
- 首先第一层
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
// 看看有没有现成的merged的,有就直接取
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
- 第二层
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
下面感兴趣可以自己看下。
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = 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) {
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)) {
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 an AbstractBeanFactory 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(RootBeanDefinition.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.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Only cache the merged bean definition if we're already about to create an
// instance of the bean, or at least have already created an instance before.
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
return mbd;
}
}
2.5.4 getSingleton(String beanName, ObjectFactory<?> singletonFactory)类
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 先上锁,锁singletonObjects对象
synchronized (this.singletonObjects) {
// 缓存里取一下
Object singletonObject = this.singletonObjects.get(beanName);
// 没取到
if (singletonObject == null) {
// 判断是否正在销毁,默认属性为false
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 + "'");
}
// 单例创建前回调
// 判断beanName在不在当前在创建检查中排除的bean名称缓存中
// 加入当前正在创建的bean的名称缓存
// 上面两个有一个失败false则抛BeanCurrentlyInCreationException异常
// 下面附了beforeSingletonCreation的源码,一看就懂
//protected void beforeSingletonCreation(String beanName) {
// if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
// throw new BeanCurrentlyInCreationException(beanName);
// }
//}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 这个singletonFactory就是回调函数,getObject()就是调用回调函数
// 这里 getObject()返回是主流程中的return createBean(beanName, mbd, args);
// 详见4.1
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;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
可以看出整个逻辑还是比较简单的,重点是creatBean这个函数了。
欲知后事如何,请看下一篇。