Spring源码分析(六)Bean的加载过程

经过前面的分析我们已经结束了对XML配置文件的解析,接下来我们来看对Bean的加载

package org.springframework.shu;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

/**
 * @description: 测试Bean
 * @author: shu
 * @createDate: 2023/4/3 14:56
 * @version: 1.0
 */
public class AppTest {
    
    
	public static void main(String[] args) {
    
    
		BeanFactory bf = new XmlBeanFactory( new ClassPathResource("spring-config.xml"));
		MyTestBean myTestBean = (MyTestBean) bf.getBean("myTestBean");
		System.out.println(myTestBean.getName());
	}
}

下面我们仔细来看看呗
AbstractBeanFactory

    	// 调用重载方法
		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 {
    
    
            
                  //提取对应的beanName
                  final String beanName = transformedBeanName(name);
                  Object bean;
                  /*
                  * 检查缓存中或者实例工厂中是否有对应的实例
                  * 为什么首先会使用这段代码呢,
                  * 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,
                  * Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光
                  * 也就是将ObjectFactory加入到缓存中,一旦下个bean创建时候需要依赖上个bean则直接使用
    ObjectFactory
                  */
                  //直接尝试从缓存获取或者singletonFactories中的ObjectFactory中获取
                  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 + "'");
    }
                      }
        //返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
                      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
                  }else {
    
    
                      //只有在单例情况才会尝试解决循环依赖,原型模式情况下,如果存在
                      //A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为
                      //对于B的创建再次返回创建A,造成循环依赖,也就是下面的情况
                      //isPrototypeCurrentlyInCreation(beanName)为true
                      if (isPrototypeCurrentlyInCreation(beanName)) {
    
    
    throw new BeanCurrentlyInCreationException(beanName);
                      }
                      BeanFactory parentBeanFactory = getParentBeanFactory();
                      //如果 beanDefinitionMap 中也就是在所有已经加载的类中不包括 beanName 则尝试从
    parentBeanFactory中检测
                      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    
    
                           String nameToLookup = originalBeanName(name);
                           //递归到BeanFactory中寻找
                           if (args != null) {
    
    
                                return (T) parentBeanFactory.getBean(nameToLookup, args);
                           }
                           else {
    
    
                               return parentBeanFactory.getBean(nameToLookup, requiredType);
                           }
                      }
                      //如果不是仅仅做类型检查则是创建bean,这里要进行记录
                      if (!typeCheckOnly) {
    
    
                          markBeanAsCreated(beanName);
                      }
                      //将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如果指BeanName是子Bean的话同时会合并父类的相关属性
                      final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                      checkMergedBeanDefinition(mbd, beanName, args);
                      String[] dependsOn = mbd.getDependsOn();
                      //若存在依赖则需要递归实例化依赖的bean
                      if (dependsOn != null) {
    
    
                           for (String dependsOnBean : dependsOn) {
    
    
                                getBean(dependsOnBean);
                                //缓存依赖调用
                                registerDependentBean(dependsOnBean, beanName);
                           }
                      }
                      //实例化依赖的bean后便可以实例化mbd本身了
                      //singleton模式的创建
                      if (mbd.isSingleton()) {
    
    
                          sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    
    
                              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()) {
    
    
                       //prototype模式的创建(new)
                       Object prototypeInstance = null;
                       try {
    
    
                           beforePrototypeCreation(beanName);
                           prototypeInstance = createBean(beanName, mbd, args);
                       }
                       finally {
    
    
                            afterPrototypeCreation(beanName);
                       } 
                       bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                  }else {
    
    
                      //指定的scope上实例化bean
                      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);
                        }
                    }
               }
                  //检查需要的类型是否符合bean的实际类型
                  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;
        }

上面的代码刚看可能有点蒙,下面我们来梳理一下大体的流程

  • ** 转换对应beanName**

或许很多人不理解转换对应beanName是什么意思,传入的参数name不就是beanName吗?其实不是,这里传入的参数可能是别名,也可能是FactoryBean,所以需要进行一系列的解析,这些解析内容包括如下内容。
去除FactoryBean的修饰符,也就是如果name=“&aa”,那么会首先去除&而使name=“aa”。
取指定alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B;若别名A指向别名B,别名B又指向名称为C的bean则返回C。

  • 尝试从缓存中加载单例

单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。当然这里也只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory

  • bean的实例化

如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。这里有必要强调一下,缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean。举个例子,假如我们需要对工厂bean进行处理,那么这里得到的其实是工厂bean的初始状态,但是我们真正需要的是工厂bean中定义的factory-method方法中返回的bean,而getObjectForBeanInstance就是完成这个工作的,后续会详细讲解。

  • 原型模式的依赖检查

只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况:isPrototypeCurrentlyInCreation(beanName)判断true。

  • 检测parentBeanFactory

从代码上看,如果缓存没有数据的话直接转到父类工厂上去加载了,这是为什么呢?可能读者忽略了一个很重要的判断条件:parentBeanFactory != null &&!containsBean Definition (beanName),parentBeanFactory != null。parentBeanFactory如果为空,则其他一切都是浮云,这个没什么说的,但是!containsBeanDefinition(beanName)就比较重要了,它是在检测如果当前加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory去尝试下了,然后再去递归的调用getBean方法。

  • 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition

因为从XML配置文件中读取到的Bean信息是存储在GernericBeanDefinition中的,但是所有的Bean后续处理都是针对于RootBeanDefinition的,所以这里需要进行一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性。

  • 寻找依赖

因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺寻中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖

  • 针对不同的scope进行bean的创建

在Spring中存在着不同的scope,其中默认的是singleton,但是还有些其他的配置诸如prototype、request之类的。在这个步骤中,Spring会根据不同的配置进行不同的初始化策略。

  • 类型转换

程序到这里返回bean后已经基本结束了,通常对该方法的调用参数requiredType是为空的,但是可能会存在这样的情况,返回的bean其实是个String,但是requiredType却传入Integer类型,那么这时候本步骤就会起作用了,它的功能是将返回的bean转换为requiredType所指定的类型。当然,String转换为Integer是最简单的一种转换,在Spring中提供了各种各样的转换器,用户也可以自己扩展转换器来满足需求。
这就是上面的代码的一个基本流程,看起来代码不多,其实代码十分复杂,我们接着往下看,根据上面的流程我们一一拆解

1.1 转换对应beanName

// 提取对应的beanName
String beanName = transformedBeanName(name);

这里我们也许会有疑问,我们一般不就传入的就是我们命名的beanName吗?为啥还需要转换一下?
我们可以从源码中可以看到,它对传入的名称进行了一下判断
BeanFactoryUtils

	public static String transformedBeanName(String name) {
    
    
		Assert.notNull(name, "'name' must not be null");
		// String FACTORY_BEAN_PREFIX = "&";
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
    
    
			return name;
		}
    	// 如果是String FACTORY_BEAN_PREFIX = "&";
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
    
    
			do {
    
    
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}

image.png
那什么时候会在beanName前显示的加上"&" 前缀?简单来说就是继承了FactoryBean,下面我们来看代码实战

说明

package com.shu.model;

/**
 * @description:
 * @author: shu
 * @createDate: 2023/8/29 9:47
 * @version: 1.0
 */
public class Car {
    
    
    private int maxSpeed;
    private String brand;
    private double price;

    public int getMaxSpeed() {
    
    
        return this.maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
    
    
        this.maxSpeed = maxSpeed;
    }

    public String getBrand() {
    
    
        return this.brand;
    }

    public void setBrand(String brand) {
    
    
        this.brand = brand;
    }

    public double getPrice() {
    
    
        return this.price;
    }

    public void setPrice(double price) {
    
    
        this.price = price;
    }
}


package com.shu.test;

import com.shu.model.Car;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
import org.springframework.beans.factory.ListableBeanFactory;

/**
 * @description: FactoryBean接口的实现类,用于测试FactoryBean的使用
 * @author: shu
 * @createDate: 2023/8/29 9:47
 * @version: 1.0
 */
public class CarFactoryBean implements FactoryBean<Car>{
    
    
    private  String carInfo ;


    public  Car getObject ()   throws  Exception  {
    
    
        Car car =  new  Car () ;
        car.setBrand ( "红旗CA72" ) ;
        car.setMaxSpeed ( 200 ) ;
        car.setPrice ( 1000000 ) ;
        return  car;
    }

    public  Class<Car> getObjectType ()   {
    
    
        return  Car. class ;
    }

    public   boolean  isSingleton ()   {
    
    
        return   false ;
    }

    public  String getCarInfo ()   {
    
    
        return   this . carInfo ;
    }



}

而我们的配置文件中

<bean name="car" class="com.shu.test.CarFactoryBean" />
/**
     * 测试FactoryBean
     */
    @Test
    public void factoryBeanTest() {
    
    
        BeanFactory bf = new XmlBeanFactory( new ClassPathResource("applicationContext.xml"));
        Object car = bf.getBean("&car");
        System.out.println(car);

    }

image.png
当调用getBean(“car”)时,Spring通过反射机制发现CarFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法CarFactoryBean#getObject()方法返回。如果希望获取CarFactoryBean的实例,则需要在使用getBean(beanName)方法时在beanName前显示的加上"&" 前缀,请注意有&符号和没有&符号获取的对象不一样
最后一步,转换别名,我们的bean实例可能会有多个别名

// 转换 aliasName
	public String canonicalName(String name) {
    
    
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
    
    
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
    
    
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

总结一下:

  • 去除 FactoryBean 的修饰符。如果 name 以 “&” 为前缀,那么会去掉该 “&”
  • 指定的 alias 所表示的最终 beanName。主要是一个循环获取 beanName 的过程,例如别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 C。

1.2 尝试从缓存中加载单例

  • 单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试尝试从singletonFactories中加载。
  • 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖, Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory。

AbstractBeanFactory

Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
    
    
			if (logger.isTraceEnabled()) {
    
    
				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 + "'");
				}
			}
			//   //返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

首先我们理清关系:

  • singletonObjects:用于保存BeanName和创建bean实例之间的关系,bean name --> bean instance。
  • singletonFactories:用于保存BeanName和创建bean的工厂之间的关系,bean name ->ObjectFactory。
  • ** earlySingletonObjects:也是保存BeanName和创建bean实例之间的关系,与singletonObjects的不同之处在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用。**
  • ** registeredSingletons:用来保存当前所有已注册的bean。**

我们可以看到关键的方法在于getSingleton,下面我们仔细来看看

        public Object getSingleton(String beanName) {
    
    
             //参数true设置标识允许早期依赖
           return getSingleton(beanName, true);
        }


        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    
    
                  //检查缓存中是否存在实例
                  Object singletonObject = this.singletonObjects.get(beanName);
                  if (singletonObject == null) {
    
    
                       //如果为空,则锁定全局变量并进行处理
                       synchronized (this.singletonObjects) {
    
    
                            //如果此bean正在加载则不处理
                            singletonObject = this.earlySingletonObjects.get(beanName);
                            if (singletonObject == null && allowEarlyReference) {
    
    
                                 //当某些方法需要提前初始化的时候则会调用 addSingletonFactory 方法将对应ObjectFactory初始化策略存储在singletonFactories
                              ObjectFactory  singletonFactory  =  this.singletonFactories.get
    (beanName);
                              if (singletonFactory != null) {
    
    
                                   //调用预先设定的getObject方法
                                   singletonObject = singletonFactory.getObject();
                                   //记录在缓存中,earlySingletonObjects和singletonFactories互斥
                                   this.earlySingletonObjects.put(beanName, singletonObject);
                                   this.singletonFactories.remove(beanName);
                              }
                          }
                      }
                  }
                  return (singletonObject != NULL_OBJECT ? singletonObject : null);
          }

我们梳理一下过程:

  • 这个方法首先尝试从singletonObjects里面获取实例
  • 如果获取不到再从earlySingleton Objects里面获取
  • 如果还获取不到,再尝试从singletonFactories里面获取beanName对应的ObjectFactory
  • 然后调用这个ObjectFactory的getObject来创建bean,并放到earlySingleton Objects里面去
  • 并且从singletonFacotories里面remove掉这个ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是在allowEarlyReference为true的情况下才会使用。

1.3 bean的实例化

如果我们其他地方使用了该Bean,然后我们再次获取该Bean就会发现它尝试从缓存中加载
image.png
接着上面我们如果从缓存中加载到了单例对象,下面就是bean的实例化,从上面的代码来看我们无论从singletonObjects还是ObjectFactory中加载的单例对象都是原始对象,所以要进行bean的实例化
:::warning
请注意下面的逻辑是正对实现了FactoryBean接口的bean,且缓存中存在,也就是说第二次使用
:::

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

image.png

  • getObjectForBeanInstance是个高频率使用的方法,无论是从缓存中获得bean还是根据不同的scope策略加载bean。
  • 我们得到bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值。
        protected Object getObjectForBeanInstance(
                      Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
    
    
                  //如果指定的name是工厂相关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通过
                  if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof
    FactoryBean)) {
    
    
                      throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.
    getClass());
                  }
                  //现在我们有了个bean的实例,这个实例可能会是正常的bean或者是FactoryBean
                  //如果是 FactoryBean 我们使用它创建实例,但是如果用户想要直接获取工厂实例而不是工厂的
    getObject方法对应的实例那么传入的name应该加入前缀&
                  if  (!(beanInstance  instanceof  FactoryBean)  ||  BeanFactoryUtils.  IsFactory
    Dereference(name)) {
    
    
                      return beanInstance;
                  }
                  //加载FactoryBean
                  Object object = null;
                  if (mbd == null) {
    
    
                       //尝试从缓存中加载bean
                       object = getCachedObjectForFactoryBean(beanName);
                  }
                  if (object == null) {
    
    
                       //到这里已经明确知道beanInstance一定是FactoryBean类型
                       FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
                       //containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测
    是否定义beanName
                       if (mbd == null && containsBeanDefinition(beanName)) {
    
    
                            //将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,
    如果指定BeanName是子Bean的话同时会合并父类的相关属性
                           mbd = getMergedLocalBeanDefinition(beanName);
                      }
                      //是否是用户定义的而不是应用程序本身定义的
                      boolean synthetic = (mbd != null && mbd.isSynthetic());
                      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
                  }
                  return object;
        }

情况一:正常的bean
image.png
情况二:FactoryBean
image.png
image.png
流程梳理:

  • 对FactoryBean正确性的验证
  • 对非FactoryBean不做任何处理
  • 尝试从缓存中加载Bean,如果有直接换行,存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition后面会详细解释
  • 缓存中有的话,交给getObjectFromFactoryBean方法进行处理,去执行FactoryBean接口实现类的getObject()也就是CarFactoryBean中的getObject方法
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    
    
		// 判断是否是单例模式 && singletonObjects 尚未缓存该bean (containsSingleton调用的是 singletonObjects )
		if (factory.isSingleton() && containsSingleton(beanName)) {
    
    
			synchronized (getSingletonMutex()) {
    
    
				// 尝试从 factoryBeanObjectCache 缓存中获取
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
    
    
					// 在这个方法中进行解析。调用 FactoryBean 的 getObject 方法
					object = doGetObjectFromFactoryBean(factory, beanName);

					// 因为是单例模式,所以要保证变量的全局唯一。所以这里如果缓存中已经创建好了bean则替换为已经创建好的bean
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
    
    
						object = alreadyThere;
					}
					else {
    
    
						// 如果允许调用bean的后置处理器。因为这里是直接将bean创建返回了,如果要调用后置方法则只能在这里调用。
						if (shouldPostProcess) {
    
    
							if (isSingletonCurrentlyInCreation(beanName)) {
    
    
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							// 将beanName 添加到 singletonsCurrentlyInCreation 中缓存,表示当前bean正在创建中
							beforeSingletonCreation(beanName);
							try {
    
    
								// 调用了ObjectFactory的后置处理器。
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
    
    
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
    
    
							// 将beanName 从 singletonsCurrentlyInCreation 中移除,表示当前bean已经创建结束
								afterSingletonCreation(beanName);
							}
						}
						// return this.singletonObjects.containsKey(beanName); 如果 singletonObjects缓存中存在当前beanName,则将其缓存到 factoryBeanObjectCache 中。
						if (containsSingleton(beanName)) {
    
    
							// 这里保存的是 beanName : FactoryBean
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
    
    
			// FactoryBean 非单例直接调用 getObject 方法
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			// 如果允许调用后置方法,则调用postProcessObjectFromFactoryBean 方法
			if (shouldPostProcess) {
    
    
				try {
    
    
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
    
    
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

	

image.png
下面我们来看看关键的核心方法doGetObjectFromFactoryBean,也就是上面CarFactoryBean实现的核心逻辑

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
    
    
    Object object;
    try {
    
    
        // 权限访问
        if (System.getSecurityManager() != null) {
    
    
            AccessControlContext acc = this.getAccessControlContext();
            try {
    
    
                object = AccessController.doPrivileged(factory::getObject, acc);
            } 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) {
    
    
        if (this.isSingletonCurrentlyInCreation(beanName)) {
    
    
            throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
        }
 
        object = new NullBean();
    }
 
    return object;
}

image.png
image.png
我们简单梳理一下上面的代码逻辑:我们的目的从工厂中加载对象,让后在调用后置处理器,在实际开发过程中可以针对进行自己的业务逻辑设计
我们来总结一下:

  • 我们尝试从缓存中加载实例对象,一般第一次使用肯定没有的,那就第二次使用的时候
  • 由于我们从缓存中尝试加载的对象是原始对象,因此我们需要实例化它
  • 但是实例化的时候分为正常情况的Bean与实现了FactoryBean接口的Bean
  • 正常情况下的Bean直接返回,复杂情况的Bean需要调用我们自己实现了FactoryBean接口的getObject方法来实例它

1.4 原型模式的依赖检查

之前我们讲解了从缓存中获取单例的过程,上面的逻辑是正对缓存中不为空的情况,下面我们来看那可能缓存如果为空咋办,那就是第一次进行初始化呗,我们接着往下看?
只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况:isPrototypeCurrentlyInCreation(beanName)判断true。

// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
	if (isPrototypeCurrentlyInCreation(beanName)) {
    
    
				throw new BeanCurrentlyInCreationException(beanName);
			}


protected boolean isPrototypeCurrentlyInCreation(String beanName) {
    
    
		Object curVal = this.prototypesCurrentlyInCreation.get();
		return (curVal != null &&
				(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
	}

image.png
总结一下:

  • 对于单例模式 Spring 在创建 bean 的时候并不是等 bean 完全创建完成后才会将 bean 添加至缓存中,而是不等 bean 创建完成就会将创建 bean 的 ObjectFactory 提早加入到缓存中,这样一旦下一个 bean 创建的时候需要依赖 bean 时则直接使用 ObjectFactroy。
  • 但是原型模式我们知道是没法使用缓存的,所以 Spring 对原型模式的循环依赖处理策略则是不处理

1.5 检测parentBeanFactory

若 containsBeanDefinition 中不存在 beanName 相对应的 BeanDefinition,则从 parentBeanFactory 中获取。
AbstractBeanFactory

//AbstractBeanFactory.java
 
// 获取父容器
BeanFactory parentBeanFactory = getParentBeanFactory();
// 检查父容器
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    
    
    // 获取原始 beanName
    String nameToLookup = originalBeanName(name);
    // 如果,父类容器为 AbstractBeanFactory ,直接递归查找
    if (parentBeanFactory instanceof AbstractBeanFactory) {
    
    
        return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
        // 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象
    } else if (args != null) {
    
    
        return (T)parentBeanFactory.getBean(nameToLookup, args);
        // 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象
    } else if (requiredType != null) {
    
    
        return parentBeanFactory.getBean(nameToLookup, requiredType);
        // 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象
    } else {
    
    
        return (T)parentBeanFactory.getBean(nameToLookup);
    }
}

获取父容器
AbstractBeanFactory

//AbstractBeanFactory.java
 
private BeanFactory parentBeanFactory;
 
@Override
public BeanFactory getParentBeanFactory() {
    
    
    return this.parentBeanFactory;
}

若父容器不为空,并且 beanDefinitionMap 中没有找到对应的 BeanDefinition 对象
DefaultListableBeanFactory

//DefaultListableBeanFactory.java
 
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
 
@Override
public boolean containsBeanDefinition(String beanName) {
    
    
	Assert.notNull(beanName, "Bean name must not be null");
	return this.beanDefinitionMap.containsKey(beanName);
}

获取原始 beanName
AbstractBeanFactory

//AbstractBeanFactory.java
 
protected String originalBeanName(String name) {
    
    
    String beanName = transformedBeanName(name); // <x>
    if (name.startsWith(FACTORY_BEAN_PREFIX)) {
    
     // <y>
        beanName = FACTORY_BEAN_PREFIX + beanName;
    }
    return beanName;
}
  • 处,AbstractBeanFactory#transformedBeanName(String name) 方法,是对 name 进行转换,获取真正的 beanName。参考前面转换对应的Bean
  • 处,如果 name 是以 “&” 开头的,则加上 “&” ,因为在AbstractBeanFactory#transformedBeanName(String name) 方法中把 “&” 去掉,这边需要补上

委托父容器加载 Bean 的逻辑
AbstractBeanFactory

// 如果,父类容器为 AbstractBeanFactory ,直接递归查找
if (parentBeanFactory instanceof AbstractBeanFactory) {
    
    
    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
    // 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象
} else if (args != null) {
    
    
    return (T)parentBeanFactory.getBean(nameToLookup, args);
    // 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象
} else if (requiredType != null) {
    
    
    return parentBeanFactory.getBean(nameToLookup, requiredType);
    // 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象
} else {
    
    
    return (T)parentBeanFactory.getBean(nameToLookup);
}

1.6 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition

参考博客:Spring中BeanDefinition的合并getMergedLocalBeanDefinition
在GenericBeanDefinition,ChildBeanDefinition中有一个parentName属性,表示该BeanDefinition的父BeanDefinition,如果该bean在定义中设置了parentName,那么在实例化之前会进行这两个BeanDefinition的合并。
获取 RootBeanDefinition
AbstractBeanFactory

//AbstractBeanFactory.java
 
// 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);

接着获取RootBeanDefinition对象

	 //返回一个合并的 RootBeanDefinition,如果该bean定义是一个子bean定义,则遍历父bean定义
	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    
    
		//先从mergedBeanDefinitions容器中取
		//如果有,表示该bean定义已经合并过了,则就直接返回;如果没有,则进行合并
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null) {
    
    
			return mbd;
		}
        // // 如果返回的 BeanDefinition 是子类 bean 的话,则合并父类相关属性
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}
  • 如果 mergedBeanDefinitions 缓存中存在对应的 RootBeanDefinition 对象,则直接返回。
  • 否则调用AbstractBeanFactory#getMergedBeanDefinition(String beanName, BeanDefinition bd)获取 RootBeanDefinition 对象
    • 通过 AbstractBeanFactory#getBeanDefinition(String beanName) 获取 BeanDefinition 对象,如果没有找到就抛出 NoSuchBeanDefinitionException 异常。
   
	/* 
	 * 如果该bean定义是子bean定义,则通过与父级合并返回给定顶级 bean 的 RootBeanDefinition
	 * @param beanName bean定义的名称
	 * @param bd 原始的bean定义(Root/ChildBeanDefinition)
	 * @return 给定bean的(可能合并的)RootBeanDefinition
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
			throws BeanDefinitionStoreException {
    
    
		return getMergedBeanDefinition(beanName, bd, null);
	}

	/**
	 * 返回一个合并的RootBeanDefinition,如果该bean定义是一个子bean定义,则合并父bean定义
	 * @param bean定义的名称
	 * @param bd 原始的bean定义(Root/ChildBeanDefinition)
	 * @param containingBd 如果是内部bean,则包含bean定义,如果是顶级 bean,则为null
	 * @return 给定bean的(可能合并的)RootBeanDefinition
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {
    
    

		synchronized (this.mergedBeanDefinitions) {
    
    
			RootBeanDefinition mbd = null;
			if (containingBd == null) {
    
    
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			if (mbd == null) {
    
    
                //如果该bean定义没有parent,则不进行合并,返回包装后的RootBeanDefinition
				if (bd.getParentName() == null) {
    
    
					//如果该bean定义是RootBeanDefinition,则直接克隆一份BeanDefinition
					if (bd instanceof RootBeanDefinition) {
    
    
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
                    //如果不是RootBeanDefinition,则包装为RootBeanDefinition
					else {
    
    
						mbd = new RootBeanDefinition(bd);
					}
				}
                //如果该bean定义有parent
				else {
    
    
					// Child bean definition: needs to be merged with parent.
					BeanDefinition pbd;
					try {
    
    
						String parentBeanName = transformedBeanName(bd.getParentName());
                        //如果parentName不是当前的beanName,则获取父bean合并后的bean定义
						if (!beanName.equals(parentBeanName)) {
    
    
                            //递归调用进行父bean定义的合并
							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);
                    //进行覆盖,用子bean定义中的属性,方法覆盖父bean定义中的属性,方法
					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());
				}

                //将合并后的bean定义放入到缓存中
				if (containingBd == null && isCacheBeanMetadata()) {
    
    
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}
			return mbd;
		}
	}
	/**
	 * 返回给定bean名称合并后的BeanDefinition,如有必要,将子bean定义与其父 bean 合并。
	 * <p>这个getMergedBeanDefinition也考虑了祖先中的 bean 定义。
	 * @param name the name of the bean to retrieve the merged definition for
	 * (may be an alias)
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	@Override
	public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
    
    
		String beanName = transformedBeanName(name);
		// Efficiently check whether bean definition exists in this factory.
		if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
    
    
			return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
		}
		//在本地解析合并的 bean 定义
		return getMergedLocalBeanDefinition(beanName);
	}

image.png
image.png
AbstractBeanDefinition中对bean定义的覆盖

/**
	 * Override settings in this bean definition (presumably a copied parent
	 * from a parent-child inheritance relationship) from the given bean
	 * definition (presumably the child).
	 * <ul>
	 * <li>Will override beanClass if specified in the given bean definition.
	 * <li>Will always take {@code abstract}, {@code scope},
	 * {@code lazyInit}, {@code autowireMode}, {@code dependencyCheck},
	 * and {@code dependsOn} from the given bean definition.
	 * <li>Will add {@code constructorArgumentValues}, {@code propertyValues},
	 * {@code methodOverrides} from the given bean definition to existing ones.
	 * <li>Will override {@code factoryBeanName}, {@code factoryMethodName},
	 * {@code initMethodName}, and {@code destroyMethodName} if specified
	 * in the given bean definition.
	 * </ul>
	 */
	public void overrideFrom(BeanDefinition other) {
    
    
		//如有直接覆盖BeanClassName
		if (StringUtils.hasLength(other.getBeanClassName())) {
    
    
			setBeanClassName(other.getBeanClassName());
		}
		//如有作用域直接覆盖作用域
		if (StringUtils.hasLength(other.getScope())) {
    
    
			setScope(other.getScope());
		}
		//覆盖是否抽象
		setAbstract(other.isAbstract());
		//覆盖是否懒加载
		setLazyInit(other.isLazyInit());
		//覆盖工厂名
		if (StringUtils.hasLength(other.getFactoryBeanName())) {
    
    
			setFactoryBeanName(other.getFactoryBeanName());
		}
		//覆盖工厂方法名
		if (StringUtils.hasLength(other.getFactoryMethodName())) {
    
    
			setFactoryMethodName(other.getFactoryMethodName());
		}
		setRole(other.getRole());
		setSource(other.getSource());
		//拷贝属性
		copyAttributesFrom(other);

		if (other instanceof AbstractBeanDefinition) {
    
    
			AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
			if (otherAbd.hasBeanClass()) {
    
    
				setBeanClass(otherAbd.getBeanClass());
			}
			if (otherAbd.hasConstructorArgumentValues()) {
    
    
				getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
			}
			if (otherAbd.hasPropertyValues()) {
    
    
				getPropertyValues().addPropertyValues(other.getPropertyValues());
			}
			if (otherAbd.hasMethodOverrides()) {
    
    
				getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
			}
			setAutowireMode(otherAbd.getAutowireMode());
			setDependencyCheck(otherAbd.getDependencyCheck());
			setDependsOn(otherAbd.getDependsOn());
			setAutowireCandidate(otherAbd.isAutowireCandidate());
			setPrimary(otherAbd.isPrimary());
			copyQualifiersFrom(otherAbd);
			setInstanceSupplier(otherAbd.getInstanceSupplier());
			setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
			setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
			if (otherAbd.getInitMethodName() != null) {
    
    
				setInitMethodName(otherAbd.getInitMethodName());
				setEnforceInitMethod(otherAbd.isEnforceInitMethod());
			}
			if (otherAbd.getDestroyMethodName() != null) {
    
    
				setDestroyMethodName(otherAbd.getDestroyMethodName());
				setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
			}
			setSynthetic(otherAbd.isSynthetic());
			setResource(otherAbd.getResource());
		}
		else {
    
    
			getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
			getPropertyValues().addPropertyValues(other.getPropertyValues());
			setResourceDescription(other.getResourceDescription());
		}
	}

	
	protected void copyAttributesFrom(AttributeAccessor source) {
    
    
		Assert.notNull(source, "Source must not be null");
		String[] attributeNames = source.attributeNames();
		for (String attributeName : attributeNames) {
    
    
			setAttribute(attributeName, source.getAttribute(attributeName));
		}
	}

1.7 寻找依赖

如果一个 bean 有依赖 bean 的话,那么在初始化该 bean 时是需要先初始化它所依赖的 bean

        // 获取依赖。
        // 在初始化 bean 时解析 depends-on 标签时设置
        String[] dependsOn = mbd.getDependsOn();
        if (dependsOn != null) {
    
    
            // 迭代依赖
        for (String dep : dependsOn) {
    
    
            // 检验依赖的bean 是否已经注册给当前 bean 获取其他传递依赖bean
            if (isDependent(beanName, dep)) {
    
    
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
            }
            // 注册到依赖bean中
            registerDependentBean(dep, beanName);
            try {
    
    
                // 调用 getBean 初始化依赖bean
                getBean(dep);
            }
            catch (NoSuchBeanDefinitionException ex) {
    
    
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
            }
        }
    }

在spring中有一个@DependsOn注解,它的作用是依赖加载,比如A对象要在B对象加载之后才能加载,那么可以在A上面加@DependsOn(value = “B”)注解,就可以达到我们的要求。

  • 通过我们前面从IoC容器中拿到的BeanDefinition,调用mbd.getDependsOn()方法,获取当前bean所有的依赖。
	@Override
	@Nullable
	public String[] getDependsOn() {
    
    
		return this.dependsOn;
	}
  • 遍历这些依赖,判断此依赖是否已注册给当前的Bean
	// 保存的是bean与其依赖的映射关系:B - > A
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

        //保存的是bean与其依赖的映射关系:A - > B
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

	//为指定的Bean注入依赖的Bean
	public void registerDependentBean(String beanName, String dependentBeanName) {
    
    
	// A quick check for an existing entry upfront, avoiding synchronization...
	//获取原始beanName
	String canonicalName = canonicalName(beanName);
	Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
	if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) {
    
    
		return;
	}

	// No entry yet -> fully synchronized manipulation of the dependentBeans Set
	//先从容器中:bean名称-->全部依赖Bean名称集合找查找给定名称Bean的依赖Bean
	synchronized (this.dependentBeanMap) {
    
    
		//获取给定名称Bean的所有依赖Bean名称
		dependentBeans = this.dependentBeanMap.get(canonicalName);
		if (dependentBeans == null) {
    
    
			//为Bean设置依赖Bean信息
			dependentBeans = new LinkedHashSet<>(8);
			this.dependentBeanMap.put(canonicalName, dependentBeans);
		}
		//把映射关系存入集合
		dependentBeans.add(dependentBeanName);
	}
	//从容器中:bean名称-->指定名称Bean的依赖Bean集合找查找给定名称Bean的依赖Bean
	synchronized (this.dependenciesForBeanMap) {
    
    
		Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
		if (dependenciesForBean == null) {
    
    
			dependenciesForBean = new LinkedHashSet<>(8);
			this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
		}
		//把映射关系存入集合
		dependenciesForBean.add(canonicalName);
	}
	}

套用上面的例子,如果 A@DependsOn(value = “B”) ,也就是说A依赖于B,那么该方法registerDependentBean(dep, beanName)中,参数 dep 就是B,beanName 就是A。
这段代码中其实就是把bean之间的依赖关系注册到两个map中。

  • dependentBeanMap 存入(B,A)
  • dependenciesForBeanMap 存入(A,B)
  • 递归调用getBean(),先生成依赖的bean
try {
    
    
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
    
    
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}

总结一下:

  • 通过我们前面从IoC容器中拿到的__BeanDefinition_,调用__mbd.getDependsOn()__方法,获取当前bean所有的依赖。_
  • 遍历这些依赖,判断此依赖是否已注册给当前的Bean
  • 递归调用getBean(),先生成依赖的bean

1.8 针对不同的scope进行bean的创建

        // Create bean instance.
	//创建单例Bean
	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的实例对象
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	}

	//创建多例Bean
	else if (mbd.isPrototype()) {
    
    
		//原型模式(Prototype)是每次都会创建一个新的对象
		Object prototypeInstance = null;
		try {
    
    
			//加载前置处理,默认的功能是注册当前创建的原型对象
			beforePrototypeCreation(beanName);
			//创建指定Bean对象实例
			prototypeInstance = createBean(beanName, mbd, args);
		}
		finally {
    
    
			//加载后置处理,默认的功能告诉IOC容器指定Bean的原型对象不再创建
			afterPrototypeCreation(beanName);
		}
		//获取给定Bean的实例对象
		bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
	}

	//要创建的Bean既不是Singleton也不是Prototype
	//如:request、session、application等生命周期
	else {
    
    
		String scopeName = mbd.getScope();
		final Scope scope = this.scopes.get(scopeName);
		//Bean定义资源中没有配置生命周期范围,则Bean定义不合法
		if (scope == null) {
    
    
			throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
		}
		try {
    
    
			//这里又使用了一个匿名内部类,获取一个指定生命周期范围的实例
			Object scopedInstance = scope.get(beanName, () -> {
    
    
				//前置处理
				beforePrototypeCreation(beanName);
				try {
    
    
					return createBean(beanName, mbd, args);
				}
				finally {
    
    
					//后置处理
					afterPrototypeCreation(beanName);
				}
			});
			//获取给定Bean的实例对象
			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);
		}
	}

1.1 单例模式实例化

关键代码

            if (mbd.isSingleton()) {
    
    
					sharedInstance = getSingleton(beanName, () -> {
    
    
						try {
    
    
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
    
    
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

第一部分分析了从缓存中获取单例模式的 bean,但是如果缓存中不存在呢?则需要从头开始加载 bean,这个过程由 getSingleton() 实现。

  public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    
    
        Assert.notNull(beanName, "Bean name must not be null");
        // 全局加锁
        synchronized (this.singletonObjects) {
    
    
            // 从缓存中检查一遍
            // 因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
            Object singletonObject = this.singletonObjects.get(beanName);
            //  为空,开始加载过程
            if (singletonObject == null) {
    
    
                // 省略 部分代码

                // 加载前置处理
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                // 省略代码
                try {
    
    
                    // 初始化 bean
                    // 这个过程其实是调用 createBean() 方法
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                // 省略 catch 部分
                }
                finally {
    
    
                    // 后置处理
                    afterSingletonCreation(beanName);
                }
                // 加入缓存中
                if (newSingleton) {
    
    
                    addSingleton(beanName, singletonObject);
                }
            }
            // 直接返回
            return singletonObject;
        }
    }

其实这个过程并没有真正创建 bean,仅仅只是做了一部分准备和预处理步骤,真正获取单例 bean 的方法其实是由 singletonFactory.getObject() 这部分实现,而 singletonFactory 由回调方法产生。那么这个方法做了哪些准备呢?关键代码在于 createBean(beanName, mbd, args),后面文章详细介绍
image.png
总结一下

  • 再次检查缓存是否已经加载过,如果已经加载了则直接返回,否则开始加载过程。
  • 调用 beforeSingletonCreation() 记录加载单例 bean 之前的加载状态,即前置处理。
  • 调用参数传递的 ObjectFactory 的 getObject() 实例化 bean。
  • 调用 afterSingletonCreation() 进行加载单例后的后置处理。
  • 将结果记录并加入值缓存中,同时删除加载 bean 过程中所记录的一些辅助状态。

1.2 原型模式实例化

				else if (mbd.isPrototype()) {
    
    
					Object prototypeInstance = null;
					try {
    
    
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
    
    
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

原型模式的初始化过程很简单:直接创建一个新的实例就可以了。
过程如下:

  • 调用 beforeSingletonCreation() 记录加载原型模式 bean 之前的加载状态,即前置处理。
  • 调用 createBean() 创建一个 bean 实例对象。
  • 调用 afterSingletonCreation() 进行加载原型模式 bean 后的后置处理。
  • 调用 getObjectForBeanInstance() 从 bean 实例中获取对象。

1.3 其他作用域

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, () -> {
    
    
							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);
					}

核心流程和原型模式一样,只不过获取 bean 实例是由 scope.get() 实现,核心实现原理我们下一章具体分析

1.9 类型转换

程序到这里返回 bean 后基本已经结束了,通常对该方法的调用参数 requiredType 是为空的。
但是可能会存在这样一种情况:返回的 bean 是一个 String,但是 requiredType 却传入 Integer 类型,那么这时候本步骤就起作用了,它的功能是将返回的 bean 转换为 requiredType 所指定的类型。
当然,String 转换为 Integer 是最简单的转换,在 Spring 中提供了各种各样的转换器,用户可以扩展转换器来满足需求。

// Check if required type matches the type of the actual bean instance.
	//对创建的Bean实例对象进行类型检查
	if (requiredType != null && !requiredType.isInstance(bean)) {
    
    
	try {
    
    
	        //执行转换
		T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
		// 转换失败,抛异常
		if (convertedBean == null) {
    
    
			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
		}
		return convertedBean;
	}
	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;

猜你喜欢

转载自blog.csdn.net/weixin_44451022/article/details/132522432