Spring源码学习-容器BeanFactory(五) Bean的创建-探寻Bean的新生之路

时间:2022-03-06 19:43:21

写在前面

上面四篇文章讲了Spring是如何将配置文件一步一步转化为BeanDefinition的整个流程,下面就到了正式创建Bean对象实例的环节了,我们一起继续学习吧。

2.初始化Bean对象实例

Resource resource = new ClassPathResource("beanFactory.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Student student = beanFactory.getBean(Student.class);

仍然使用我们最开的一串代码来讲解,前四章我们说了那么多其实只是创建了BeanFactory这个容器,并将BeanDefinition对象解析完毕,而真正的对象创建则是在BeanFactory.getBean()中执行的。

2.1 起源,探寻Bean的新生之路

一切起源于BeanFactory.getBean(),而对getBean()的实现是在AbstractBeanFactory这个类中实现的,所以我们着眼此类进行源码的阅读。如下为AbstractBeanFactory的继承实现图

Spring源码学习-容器BeanFactory(五) Bean的创建-探寻Bean的新生之路

Spring源码学习-容器BeanFactory(五) Bean的创建-探寻Bean的新生之路

getBean()方法调用了本类中自定义的doGetBean方法,接下来进入doGetBean()方法观察。

protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//1、解析beanName,找出bean真正的名称
final String beanName = transformedBeanName(name);
Object bean; //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 {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//3.该容器缓存中没有,开始尝试加载父容器,检查父容器中是否存在该Bean对象
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
} if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
//4.父容器中仍然不存在,获取解析好的BeanDefinition,开始准备自己创建Bean
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//获取bean的根路径信息
checkMergedBeanDefinition(mbd, beanName, args);
//重要一步,检查依赖关系,提前创建依赖的bean对象。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}
//5.检查BeanDefinition的scope属性,并执行不同的创建方法,总体大同小异,着重关注单例的创建方法即可。
if (mbd.isSingleton()) {
//6、极为重要的一点,通过getSingleton(String beanName,ObjectFactory objectFactory)创建对象,并且实例化getObject()方法
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
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 name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
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;
}
}
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
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;
}

上面的代码很长,乍一看真的会让初学者头皮发麻,但是没关系,我们将它拆解开来一步一步分析。

  1. transformedBeanName(String):提取对应Bean的名称。定义在SimpleAliasRegistry中,用于获取bean的真实名称。
  2. DefaultSingletonBeanRegistry.getSingleton(Stirng,Boolean):尝试从缓存中直接获取bean或者通过ObjectFactory中获取。关于此方法的详解,请点击。
  3. getObjectForBeanInstance():根据Bean取出我们真正需要的对象(判断指定的bean是否是一个FactoryBean,如果是FactoryBean会判断需求的是本身还是factory的创建对象。)
  4. isPrototypeCurrentlyInCreation(beanName):判断是否进入了循环依赖的无限循环
  5. registerDependentBean(dep, beanName):此段代码主要是找出当前Bean的所有依赖对象,并且循环对这些依赖进行注册和创建。
  6. getSingleton(String,ObjectFactory):针对不同的scope进行各自的初始化操作。
  7. 做最后的类型转换(还不太懂)

至此,一个bean的完整创建流程就走完了。具体的细节,我们接下来一个一个慢慢的看。


2.2 明辨,找出我们真正的目标

首先,我们进入第一段代码

Spring源码学习-容器BeanFactory(五) Bean的创建-探寻Bean的新生之路

在transformedBeanName(beanName)中,传入的参数并非真正的beanName,这里的参数可能是别名,也可能是factoryBean的名称,所以要进行一系列的解析,主要的解析分为两步:

  1. 尝试解析是否是FactoryBean名称,(关于FactoryBean如果不理解,可以访问:Spring之FactoryBean 代码如下:
	//解析是否是FactoryBean:BeanFactoryUtils.transformedBeanName(String name)
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
String beanName = name;
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
return beanName;
}
	代码很简单,就是判断beanName是否是以“&”开头,然后进行截取。
  1. 尝试判断该名称是否是某个bean的别名。
	//判断别名:SimpleAliasRegistry.canonicalName(String name)
public String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
do {
//从别名集合中循环查找,直到最底层真正的bean名称
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
依然很简单,尝试从实现定义好的别名集合中进行查询,寻找真正的bean。

2.3 尝试从缓存中直接获取对象

接下来是doGetBean中的第三个方法,getSingleton(String beanName, boolean allowEarlyReference)

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//1.尝试从单例缓存中直接获取对象
Object singletonObject = this.singletonObjects.get(beanName);
//2.如果单例缓存中无法获取对象,且该对象在正在创建对象标记池里。
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//3.从提前创建对象池中获取该对象
singletonObject = this.earlySingletonObjects.get(beanName);
//4.对象仍然为空且允许循环依赖
if (singletonObject == null && allowEarlyReference) {
//5.尝试从ObjectFactory池中获取对象的ObjectFactory,并创建该对象。
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
} public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}

此方法代码其实不难理解,主要的难点是几个概念上的问题。首先观察该方法中用到的该类的几个参数。

  1. 单例对象缓存池
    /** Cache of singleton objects: bean name --> bean instance */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

    如注解,这是Spring的单例对象池,所有的单例对象创建完毕后都会以beanName ->singletonObject 的形式放入该Map集合中

  2. 对象预创建标记池
    /** Names of beans that are currently in creation */
    private final Set<String> singletonsCurrentlyInCreation =
    Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

    这是Spring为了解决循环依赖的一个标记集合,具体概念留在后面介绍

  3. 预创建单例对象缓存池
    /** Cache of early singleton objects: bean name --> bean instance */
    private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

    此集合是保存预创建单例对象的集合

  4. 预创建单例对象缓存池
    /** Cache of singleton factories: bean name --> ObjectFactory */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

    此集合是保存ObjectFactory的集合,至于何时、何种情况Spring会创建ObjectFactory。且ObjectFactory、BeanFacotry、FactoryBean他们的关系,也在下面会做说明。

小tip:ObjectFactory、BeanFactory、FactoryBean之间的关系和联系

  • BeanFactory:这是我们大家非常熟悉的接口,Spirng管理Bean容器最原始接口,我们此次研究的入口getBean()就是在此接口中定义。
  • FactoryBean:在上文2.2中我们已经讨论了FactoryBean的情况,作为一个Bean的工厂对象,它也可以作为一个bean对象直接获取,关于BeanFactory和FactoryBean的详细信息,可查看该文章:BeanFactory和FactoryBean
  • ObjectFactory:与FactoryBean很相似的是ObjectFactory也是用于创建一个对象的,且它存在的意义主要用于解决循环依赖。例如A、B两个对象,A中有B属性,B中有A属性。那么在创建A时发现需要注入B,这时创建B,在创建B时发现又需要注入A,这就形成了循环依赖。而Spring正是利用ObjectFactory解决了这个问题,其原理就是在创建A时就将一个A的ObjectFactory对象放入了缓存中,那么在B注入A时就用这个ObjectFactory创建的对象注入B中,这样就解决了循环依赖的问题。具体的代码在下面会详细介绍。

2.4根据Bean实例,获取真正需要的对象(FactoryBean的特殊处理场景)

getObjectForBeanInstance()是一个非常重要的方法,Spring在获取了每个Bean的对象之后,都要调用该方法完成最后的步骤以取得我们真正想要的Bean。说到很多人肯定会疑惑,什么是“真正需要”,点进该方法,我们就知道了。

protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
} //判断实例不是FactoryBean类型或该实例名称以获取FactoryBean开头 ,满足任何一个条件直接返回实例
//即满足两个条件无非有两个条件1.该对象不是FactoryBean,判断短路直接返回。2.该对象是FactoryBean,且用户想直接获取FactoryBean
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
} Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
//通过上述,至此可以完全确定该对象是Factory对象,下方就是通过对象的factory-method创建对象的过程。
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

上述重要就是一个短路判断,如果该对象不是一个FactoryBean或者用户试图直接获取FactoryBean对象,则该对象就已经是我们想要的对象,直接返回即可,否则的话就意味着我们需要通过FactoryBean内部定义好的factory-method来创建我们需要的Bean对象。而我们追入getObjectFromFactoryBean()中,查看如下代码:

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

而遗憾的是我们还是没有看到真正创建对象的方法,但通过前面的阅读,我们已经可以发现Spring在一个方法的真正核心处理部分处,都会以doXXXX开头,而其余都是对这个核心处理的一层层包装与协助。

2.4.1代码如莲花开放般的优美:处理器BeanPostProcess

在观察核心代码之前,我们先观察后面一个重要的方法。postProcessObjectFromFactoryBean(),在spring的整个架构中给予了用户各种拓展和自定义的权利,这也是Spring被广泛称赞:代码优美的原因之一。而这里的执行后处理器操作就是很重要的一环,进入该方法的子类AbstractAutowireCapableBeanFactory观察Spirng是如何让代码变得如此优美的。

	//AbstractAutowireCapableBeanFactory.java
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
} public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
//BeanPostProcessor.java
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

观察代码,可以知道Spring循环了Bean所注册的所有BeanPostProcess,并在这里依次调用了其postProcessAfterInitialization()方法,而该方法的实现交由用户来自己实现。于是乎,通过解析我们就能知道:在Spring中:如果想让一个Bean在初始化完成后做一些特殊处理,实现BeanPost.postProcessAfterInitialization()即可。最后有一个小提醒:我们一定要清晰的认识到,此时我们是在修饰一个FactoryBean创建的Bean对象,而并非正常流程创建的Bean对象哦,例如我们一直讨论的这个FactoryBean,它本身作为一个Bean对象是在什么时候执行了PostPorcess方法了呢?后续我们拭目以待吧

2.4.2柳暗花明,终于获取最终需要的对象

了解完处理器之后,让我们点入doGetObjectFromFactoryBean(),发现里面的代码就非常简单明了。

//FactoryBeanRegistrySupport.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(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
//调用Factory的getObject方法
return factory.getObject();
}
}, acc);
}catch (PrivilegedActionException pae) {
throw pae.getException();
}
}else {
//调用Factory的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);
}
if (object == null && isSingletonCurrentlyInCreation(beanName)){
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
return object;
}

一层一层终于我们到了最里边,在这里我们发现最终对象正是由当初获取的FactoryBean对象的getObject()方法完成。如果读到这里已经有些绕不过来,想不起自己从何处而来的话,往上翻一翻,看清楚自己一路走来之路哦。下面我们就重新回到起源之路上,继续往下探索。但由于真正的Bean的创建流程很长,所以这篇文章先写到这里,下面单开一篇文章来写Bean对象的实例化。