Spring 源码学习(4)—— bean的加载part 1

时间:2023-03-09 07:09:16
Spring 源码学习(4)—— bean的加载part 1

前面随笔中,结束了对配置文件的解析工作,以及将配置文件转换成对应的BeanDefinition存储在容器中。接下来就该进行bean的加载了。

    public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
if (this.logger.isDebugEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
} bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
} BeanFactory parentBeanFactory = this.getParentBeanFactory();
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
} if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
} return parentBeanFactory.getBean(nameToLookup, requiredType);
} if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
} try {
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if (dependsOn != null) {
var11 = dependsOn;
int var12 = dependsOn.length; for(int var13 = 0; var13 < var12; ++var13) {
String dep = var11[var13];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
} this.registerDependentBean(dep, beanName);
this.getBean(dep);
}
} if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
var11 = null; Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
} bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
Scope 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, () -> {
this.beforePrototypeCreation(beanName); Object var4;
try {
var4 = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
} return var4;
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var21) {
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", var21);
}
}
} catch (BeansException var23) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
} if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
} else {
return convertedBean;
}
} catch (TypeMismatchException var22) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var22);
} throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
} else {
return bean;
}
}

在这段代码中,我们可以看出bean的加载经历了一个相当复杂的过程,并不是我们想象中简单的用bean的class属性通过反射的方式来实例化bean。其中涉及到方方面面的考虑,不得不佩服开发者缜密的思维。

对于bean加载的过程大致可以总结如下:

1、转换对应的beanName

String beanName = this.transformedBeanName(name);
protected String transformedBeanName(String name) {
return this.canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

这里的目的是通过name得到真正的beanName。

在BeanFactoryUtils.transformedBeanName()中将name前的‘&’符号去除。之前的随笔中有说到过,Spring除了可以通过我们常见的set注入和构造器注入的方式生成bean,还可以通过工厂方法来实例化bean。例如

<bean id="production" class="com.wuzhe.factory.MyBeanFactory"/>

这样通过beanFactory.getBean() 得到的bean就是通过MyBeanFactory实现FactoryBean的getObject()方法实例化而来的。

如果我们想要得到的MyFactoryBean本身这个bean的话,就需要在beanName前加上‘&’符号。例beanFactory.getBean("&production")

回到之前的代码中,处理完‘&’符号的name之后,在cannonicalName()方法里会遍历容器中aliasMap中维护的alia对应beanName的关系,得到真正的beanName

2、尝试从缓存中加载单例

Object sharedInstance = this.getSingleton(beanName);
@Nullable
public Object getSingleton(String beanName) {
return this.getSingleton(beanName, true);
} @Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
Map var4 = this.singletonObjects;
synchronized(this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
} return singletonObject;
}

因为单例的bean只需要初始化一次就足够了,因此在spring中,实例化过得单例bean都被存放在了缓存中,一旦后续再尝试获取该bean时,只需要从缓存中获取就足够了。

在读spring的源码时,经常被spring容器中的各种缓存搞的云里雾里,所以在解读之前先把我们将要用到的缓存名以及其用意列举一下。

singletonObjects:

维护了容器中已被实例化过的单例bean。通过beanName -> Object

factoryBeanObjectCache:

维护了容器中单例工厂FactoryBean对象getObject()得到的单例bean。通过beanName -> Object

singletonsCurrentlyInCreation:

存放了当前正在实例化中的单例bean beanName的集合。 Set<beanName>

earlySingletonObjects:

维护了容器中单例bean。通过beanName -> Object。和singletonObjects的区别是singletonObjects中存放的是已经实例化完成的bean,而在一个bean还未实例化完成时,spring就会通过对应的ObjectFactory的getObject()方法返回一个bean的引用并存放在earlySingletonObjects中,对于后面可能遇到的循环依赖有大用处。

singletonFactories:

维护了容器中还未生产过单例的ObjectFactory。通过beanName -> ObjectFactory。一旦某个ObjectFactory生产过bean,则这个bean会被放置到earlySingletonObjects中,并且这个ObjectFactory在singletonFactories中会被移除。

接下来结合getObjectForBeanInstance方法的代码一起看

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
if(BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
} else if(beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
Object object = null;
if(mbd == null) {
object = this.getCachedObjectForFactoryBean(beanName);
} if(object == null) {
FactoryBean factory = (FactoryBean)beanInstance;
if(mbd == null && this.containsBeanDefinition(beanName)) {
mbd = this.getMergedLocalBeanDefinition(beanName);
} boolean synthetic = mbd != null && mbd.isSynthetic();
object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
} return object;
} else {
return beanInstance;
}
}

我们将从缓存中获取对象的情况分成一下三种情况:

1、根据beanName在singletonObjects中能直接取到对象bean,且当前bean不是FactoryBean类,或者当前bean是FactoryBean类,但name中带有‘&’前缀:

说明这个获取得到的bean就是调用者想要获取的bean。这时只需要直接返回这个bean就可以了。

2、根据beanName在singletonObjects中能直接取到对象bean,但当前bean是FactoryBean类,且name中不带有‘&’前缀:

说明这个获取到的bean是工厂bean,调用者真正想要的是通过工厂生产出来的bean。

这时候spring并不会直接调用FactoryBean的getObject()获取bean,而是先从工厂生产的缓存factoryBeanObjectCache中查找。

protected Object getCachedObjectForFactoryBean(String beanName) {
Object object = this.factoryBeanObjectCache.get(beanName);
return object != NULL_OBJECT?object:null;
}

若找到了,则直接返回该bean。

如果没有找到,则先合并当前的beanDefinition和其父beanDefinition得到mbd。从而取到mbd的synthetic属性。这个属性标识这个bean是否是人工生成的

然后调用getObjectFromFactoryBean()方法

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if(factory.isSingleton() && this.containsSingleton(beanName)) {
synchronized(this.getSingletonMutex()) {
Object ex = this.factoryBeanObjectCache.get(beanName);
if(ex == null) {
ex = this.doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if(alreadyThere != null) {
ex = alreadyThere;
} else {
if(ex != null && shouldPostProcess) {
try {
ex = this.postProcessObjectFromFactoryBean(ex, beanName);
} catch (Throwable var9) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean\'s singleton object failed", var9);
}
} this.factoryBeanObjectCache.put(beanName, ex != null?ex:NULL_OBJECT);
}
} return ex != NULL_OBJECT?ex:null;
}
} else {
Object object = this.doGetObjectFromFactoryBean(factory, beanName);
if(object != null && shouldPostProcess) {
try {
object = this.postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable var11) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean\'s object failed", var11);
}
} return object;
}
}

如果这个factoryBean生成的不是单例的bean,则直接调用doGetObjectFromFactoryBean()方法

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if(System.getSecurityManager() != null) {
AccessControlContext ex = this.getAccessControlContext(); try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
return factory.getObject();
}
}, ex);
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
object = factory.getObject();
}
} catch (FactoryBeanNotInitializedException var7) {
throw new BeanCurrentlyInCreationException(beanName, var7.toString());
} catch (Throwable var8) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);
} if(object == null && this.isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
} else {
return object;
}
}

这里的System.getSecurityManager是获取系统的安全管理权限,在安全的情况下,调用了factoryBean的getObject()方法得到了bean。

如果这个factoryBean是单例工厂,则在通过doGetObjectFromFactoryBean()获取bean之后,将bean放置在了factoryBeanObjectCache缓存中。

这里的postProcessObjectFromFactoryBean方法是一个通过工厂生产bean的一个后处理器,关于后处理器在后续章节会详细了解,这里只需要知道在spring获取bean的规则中有一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理,在实际开发中,大可以针对此特性设计自己的业务逻辑。

3、根据beanName在singletonObjects中不能取到对象bean,但在singletonsCurrentlyInCreation中有此beanName:

说明这个bean正在被创建中,那么spring就会:

1)先尝试在earlySingletonObjects中查找bean的缓存,若找到了则直接返回。

2)如果还是没找到,就会在singletonFactories中查找这个beanName对应的ObjectFactory缓存,如果这时候还没找到,则需要走完创建bean的流程了,return 空。

3)如果找到了对应的ObjectFactory,则通过ObjectFactory的getObject()方法获取bean。并在将其放在earlySingletonObjects的缓存中。并在singletonFactories中移除次ObjectFactory。

这样通过缓存获取bean的过程就结束了。