前言
上文 Spring源码解读(三)Bean创建过程之注册——DefaultListableBeanFactory 中,已经分析到了DefalutListableBeanFactory将所有的Bean注册到自己的注册表中,这篇文章暂时跳过refresh()方法中的其他步骤,从getBean()方法入手,分析bean创建的逻辑。refresh()中其他逻辑在后续文章中分析。
代码入口
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ac.getBean("");
直接从 ac.getBean() 点进去,看其内部逻辑。
@Override
public Object getBean(String name) throws BeansException {
// 断言,判断上下文的 BeanFactory 当前处于活动状态,非活动状态抛出异常
assertBeanFactoryActive();
// 获取在AbstractRefreshableApplicationContext.refreshBeanFactory方法中创建的DefaultListableBeanFactory对象
// 从DefaultListableBeanFactory对象中获取注册表中缓存的bean
// 再由BeanFactory的实现类进行具体的创建过程
// 再次提醒 DefaultListableBeanFactory springBean的核心
// getBeanFactory是一个抽象方法,返回值是ConfigurableListableBeanFactory接口类型
// AbstractRefreshableApplicationContext继承了AbstractApplicationContext, 实现了getBeanFactory
return getBeanFactory().getBean(name);
}
获取BeanFactory
AbstractRefreshableApplicationContext#getBeanFactory
方法内部逻辑很简单,就直接返回这个对象中的成员变量beanFactory。这个属性就是由refreshBeanFactory方法创建的,如果对这个方法不熟悉可以看 Spring源码解读(一)启动流程分析 ,这里做了详细的介绍,并多次提到DefaultListableBeanFacory。
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
// 返回 refreshBeanFactory() 方法创建的 beanFactory
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return beanFactory;
}
这里getBeanFactory拿到的DefaultListableBeanFactory是ConfigurableListableBeanFactory接口的实现类,调用getBean方法,getBean方法是由BeanFactory顶级接口定义的,AbstractBeanFactory实现了BeanFactory接口,同时提供了一些通用的默认实现,所以DefaultListableBeanFactory.getBean实际调用的就是AcstractBeanFactory的通用实现。如果对这部分不清楚可以看上一篇博文 Spring源码解读(三)Bean创建过程之注册——DefaultListableBeanFactory 中介绍DefaultListableBeanFactory父类和接口的功能。
获取Bean入口
AbstractBeanFactory#getBean
通过beanName获取bean对象,此时不知道bean是什么类型,返回的是Object对象,使用时需要做类型转换。
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
AbstractBeanFactory#doGetBean
doGetBean是AcstractBeanFactory自己的方法,支持通过beanName、类型获取bean。
它优先从单例缓存中查找bean,如果有直接返回;如果没有,则根据不同的作用域创建bean实例,然后返回。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 此时不知道传递的beanName是主名还是别名
// 通过这一步转换,拿到bean的主名
String beanName = transformedBeanName(name);
Object bean;
// 优先从单例缓存中获取bean
// 在创建单例Bean时,如果bean存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
// Spring创建Bean的原则是 不等bean创建完成就会创建bean的ObjectFactory,提前曝光
// 提前将ObjectFactory加入到缓存中,等下一个bean创建时需要依赖这个类的直接使用ObjectFactory
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
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的子类,如果没有实现FactoryBean就直接返回
// 因为FactoryBean要通过getObject方法才能返回bean的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 循环依赖就是指 A 依赖 B, B 也依赖 A, 那么当依赖注入时,创建A时就会去创建B,创建B时又会去创建A,这就是循环依赖。
// 所以 只有单列模式下才能解决循环依赖,因为单例模式的bean是共享的。
// 当多例模式的情况下,无法解决,如果存在循环依赖,只能抛出异常
// 下面就是判断多例情况下,是不是正在被创建 存在循环依赖的情况。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 是否有BeanDefinition,如果有就不需要再创建BeanDefinition
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// bean的原名,用于父级工厂中查找
String nameToLookup = originalBeanName(name);
// 委托父级工厂获取Bean对象
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.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 类型检查,主要是判断是否在创建bean,
// 如果不仅仅做检查的话,就是在创建bean,要标记状态
if (!typeCheckOnly) {
// 将bean 标记为已创建或即将创建
markBeanAsCreated(beanName);
}
try {
// 转换为RootBeanDefinition,
// 如果是子bean的话,同时合并父类属性
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// dependsOn AbstractBeanDefinition定义的成员属性,其存放的值是<bean>标签中的depends-on属性的值,或者被@DependsOn注解的值
// 这里的依赖不是指普通的@Autowire的依赖
String[] dependsOn = mbd.getDependsOn();
// 处理当前bean的依赖,保证它依赖的bean都被初始化
if (dependsOn != null) {
for (String dep : dependsOn) {
// 当前bean的依赖是否已经注册到注册表中,可能存在循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 将这个依赖注册到注册表中,缓存起来
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 开始创建bean实例
// Create bean instance.
if (mbd.isSingleton()) {
// 调用DefaultSingletonBeanRegistry.getSingleton获取单例对象实例
// 这个方法的参数时,beanName 和 ObjectFactory, 这里new一个匿名实现类
sharedInstance = getSingleton(beanName, () -> {
try {
// 调用AbstractAutowireCapableBeanFactory.createBean
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的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 创建前置操作,将当前bean标记为正在创建
beforePrototypeCreation(beanName);
// 调用AbstractAutowireCapableBeanFactory.createBean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 创建后置操作,取消标记当前bean的正在创建状态
afterPrototypeCreation(beanName);
}
// 获取这个bean的实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
// 作用域参数 有效性验证
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
// this.scopes是一个Map, AbstractBeanFactory.registerScope 为scopes赋值
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的实例对象
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) {
// 创建失败后清除,从alreadyCreated删除
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 类型检查,已经创建的bean和实际需要类型是否一致
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 类型转换,如果这个bean无法转换成所需的类型,返回null,表示类型不一致,抛出异常
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
转换beanName
AbstractBeanFactory#transformedBeanName
调用这个方法时,传入的字符串目前我们无法得知是主名还是别名,需要通过aliasMap进行转换,同时也处理FactoryBean的修饰符“&”。
aliasMap是一个缓存主名和别名映射关系的Map,那么它是怎么来的呢?
在上一篇博文中有提到BeanDefinitionReaderUtils这个工具类,aliasMap就是在它的registerBeanDefinition方法的最后一步,调用SimpleAliasRegistry.registerAlias方法完成维护主名和别名的映射关系。
protected String transformedBeanName(String name) {
// BeanFactoryUtils.transformedBeanName 处理FactoryBean通过 & + beanName的方式获取bean
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// aliasMap 在bean注册的过程中,会将bean主名和别名添加到aliasMap中 做好映射关系
// 这里通过传入的名字在映射关系中查询到主名称
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 主beanName
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 使用此注册表注册一个新的 BeanDefinition。
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 如果有别名,注册别名
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
// 为这个bean设置别名, 调用SimpleAliasRegistry.registerAlias方法完成
registry.registerAlias(beanName, alias);
}
}
}
优先从缓存中获取bean
DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
获取bean时,优先从单例缓存中获取bean。因为单例bean只会被创建一次,获取bean时优先从单例缓存中取,如果缓存中不存的,可能会存在循环依赖的问题,这时可以直接创建这个bean,并允许提前引用当前创建的单例,从而解决循环引用。
@Nullable
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)) {
// 如果是null,并且正在加载中
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) {
// 当某些方法需要提前初始化的时候则会调用 addSingletonFactory方法将对于的ObjectFactory初始化策略存储在SingletonFactories
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
// 记录在缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// earlySingletonObjects 和 singletonFactories 互斥
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
简单介绍一下这里设计到的几个Map缓存:
- singletonObjects :缓存beanName和bean实例 ,key:beanName,value:beanInstance
- singletonFactories : 缓存beanName和beanFactory,key:beanName, vaule:ObjectFactory
- earlySingletonObjects :跟singletonObjects相同的地方是都是用来缓存beanName和bean实例的,不同点在于当一个单例的bean被放在earlySingletonObjects后,那么当bean还是在创建过程中,就可以通过getBean方法取到,目的就是为了处理循环依赖。
- registeredSingletons :用来缓存当前已经注册的bean。
这个方法内涉及到spring经典的三级缓存,三级缓存简单的讲就是通过上面几个map集合实现的,关于三级缓存可参考 Spring源码解读(六)循环依赖及三级缓存源码分析——DefaultSingletonBeanRegistry 。
首先尝试从singletonObjects离获取,如果没有再从earlySingleton中获取,如果还是没有,再从singletonFactories中通过beanName找到对应的objectFactory,并调用其getObject方法创建bean; 最后加入到singletonObjects,同时从singletonFactories中删除,因为单例bean只会被创建一次,所有两者是互斥的。当然这一切的前提都是在 allowEarlyReference=true,也就是允许提前引用的情况下才会执行的。
获取bean的实例化
AbstractBeanFactory#getObjectForBeanInstance
如果在单例缓存中已经拿到的bean的实例对象,为什么还要再调用getObjectForBeanInstance?
其实后面不同作用域的bean实例化都在调用这个方法,这个方法主要是用来FactoryBean的。
这里需要提到两个基础接口BeanFactory和FactoryBean, 名字很像,功能区别很大。
- BeanFactory 是定义Spring IOC容器的最基础的规范,只是个接口,有DefalutLisbleBeanFactory, AbstractBeanFactory等诸多实现。
- FactoryBean 是Spring提供的一种更灵活的创建bean的方式,可以自定义复杂的Bean对象的实例化和初始化。
这个方法中,判断对象如果不是FactoryBean类型,就直接返回这个实例对象。只针对FactoryBean的实现类进行处理。
关于FactoryBean的细节问题,这里暂时不做讲解。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果beanName已 & 开头,检查是否FactoryBean的派生类。
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
// 如果不是派生类,就抛出异常
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
// 不是FactoryBean 直接返回
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
多例模式下循环依赖检查
AbstractBeanFactory#isPrototypeCurrentlyInCreation
检查多例(原型)类型是否存在循环依赖,spring目前无法解决多列模式下的循环依赖问题,因为单例模式bean是共享的,多例Bean不是共享的。
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
// 根据当前线程中的多例对象集合判断,如果存在这个多例bean,则bean正在创建中,此时就可能出现了循环依赖
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
委托父级工厂创建Bean
如果当前工厂类存在父级工厂,同时父级工厂中也有这个bean的装饰类BeanDefinition,就委托父级工厂获取bean。
标记创建状态
AbstractBeanFactory#markBeanAsCreated
标记bean正在被创建
// 类型检查,主要是判断是否在创建bean,
// 如果不仅仅做检查的话,就是在创建bean,要标记状态
if (!typeCheckOnly) {
// 将bean 标记为已创建或即将创建
markBeanAsCreated(beanName);
}
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// 既然我们实际上是在创建 bean,就让 bean 定义重新合并,以防万一它的一些元数据同时发生变化。
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);
}
}
}
}
转换RootBeanDefinition
AbstractBeanFactory#getMergedLocalBeanDefinition
因为后续的处理都是针对RootBeanDeginition所以这里提起转换。
子类需要父类可被继承的属性,实例化时需要合并父类属性,同时从mergedBeanDeifition中取出这个bean的RootBeanDefinition。
最终在AbstractBeanFactory#getMergedBeanDefinition(String, BeanDefinition, BeanDefinition)完成合并,细节暂不分析
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
处理bean的依赖
注意这里的依赖不是指bean中@Autowire这种依赖,这里的depends-on是AbstractBeanDefinition定义的成员属性,其存放的值是<bean>标签中的depends-on属性的值,或者被@DependsOn注解的值。
保证当前bean实例化之前,它依赖的bean都被初始化。所以Spring在初始化某一个bean的时候,会先初始化这个bean所对于的依赖。
// dependsOn AbstractBeanDefinition定义的成员属性,其存放的值是<bean>标签中的depends-on属性的值,或者被@DependsOn注解的值
// 这里的依赖不是指普通的@Autowire的依赖
String[] dependsOn = mbd.getDependsOn();
// 处理当前bean的依赖,保证它依赖的bean都被初始化
if (dependsOn != null) {
for (String dep : dependsOn) {
// 当前bean的依赖是否已经注册到注册表中,可能存在循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 将这个依赖注册到注册表中
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
根据不同作用域处理bean的创建
这部分内容在下一篇博文分析。
类型检查
当各Score实现类创建好bean以后,检查当前创建的bean类型和所需的类型是否一致。
// 类型检查,已经创建的bean和实际需要类型是否一致
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 类型转换,如果这个bean无法转换成所需的类型,返回null,表示类型不一致,抛出异常
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
Return
最后返回创建好的bean,至此我们就可以通过beanName获取到Spring容器中的bean了。
return (T) bean;