【Spring 源码】—— IoC 之开启 Bean 的加载

1.getBean

当我们通过使用 BeanFactory#getBean(String name) 方法来获取 Bean 时候,就会触发 加载  Bean 阶段。代码如下 :

//AbstractBeanFactory.java

@Override
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}复制代码

实际调用的是 AbstractBeanFactory#doGetBean(String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly) 方法,该方法接受四个参数:

  • name :要获取 Bean 名字
  • requiredType :要获取 Bean 类型
  • args :创建 Bean 时传递的参数,该参数只会在创建 Bean 时有效
  • typeCheckOnly :是否为类型检测

2.doGetBean

AbstractBeanFactory#doGetBean(String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly)  方法就是加载 Bean 核心逻辑,代码较长,需要慢慢看。代码如下:

//AbstractBeanFactory.java

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    //<1> 返回 bean 名称,剥离工厂引用前缀。
    // 如果 name 是 alias ,则获取对应映射的 beanName 。
    final String beanName = transformedBeanName(name);
    Object bean;

    // 从缓存中或者实例工厂中获取 Bean 对象
    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 + "'");
            }
        }
        // <2> 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
        // <3> 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // <4> 如果当前容器中没有找到,则从父类容器中加载
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(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);
            }
        }

        // <5> 如果不是仅仅做类型检查则是创建bean,这里需要记录
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

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

            // <7> 处理所依赖的 bean
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // 若给定的依赖 bean 已经注册为依赖给定的 bean
                    // 即循环依赖的情况,抛出 BeanCreationException 异常
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 缓存依赖调用 TODO 芋艿
                    registerDependentBean(dep, beanName);
                    try {
                        // 递归处理依赖 Bean
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // <8> bean 实例化
            if (mbd.isSingleton()) { // 单例模式
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    } catch (BeansException ex) {
                        // 显式从单例缓存中删除 Bean 实例
                        // 因为单例模式下为了解决循环依赖,可能他已经存在了,所以销毁它。 TODO 芋艿
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            } else if (mbd.isPrototype()) { // 原型模式
                Object prototypeInstance;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                } finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            } else {
                // 获得 scopeName 对应的 Scope 对象
                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 {
                    // 从指定的 scope 下创建 bean
                    Object scopedInstance = scope.get(beanName, () -> {
                        // 加载前置处理
                        beforePrototypeCreation(beanName);
                        try {
                            // 创建 Bean 对象
                            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) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // <9> 检查需要的类型是否符合 bean 的实际类型
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            // 执行转换
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            // 转换失败,抛出 BeanNotOfRequiredTypeException 异常
            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;
}复制代码

这段代码非常长,而且逻辑超复杂,我们将拆解这段代码进行分析

2.1 获取 beanName

对应代码段如下:

//AbstractBeanFactory.java

final String beanName = transformedBeanName(name);复制代码

这里的 name 不一定是 beanName,可能是 aliasName,也有可能是 FactoryBean,所以这里需要调用 AbstractBeanFactory#transformedBeanName(String name)  方法,对 name 进行转换。代码段如下:

//AbstractBeanFactory.java

protected String transformedBeanName(String name) {
	return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}复制代码
  • 调用 BeanFactoryUtils#transformedBeanName(String name) 方法,剥离 FactoryBean 修饰符。代码段如下:

//BeanFactoryUtils.java

//缓存已经转换好的 name to beanName
private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>();

public static String transformedBeanName(String name) {
	Assert.notNull(name, "'name' must not be null");
	if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
		return name;
	}
        // name = "&userService" 
        // beanName = "userService"
	return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
		do {
		    beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
		}
		while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
		return beanName;
	});
}复制代码
  • 调用 BeanFactoryUtils#canonicalName(String name) 方法,获取 alias 最终映射的 beanName,这是一个循环获取的过程

//SimpleAliasRegistry.java
//缓存 alias to beanName
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

public String canonicalName(String name) {
	String canonicalName = name;
	String resolvedName;
	// 循环,从 aliasMap 中,获取到最终映射的 beanName
	do {
	    resolvedName = this.aliasMap.get(canonicalName);
	    if (resolvedName != null) {
	        canonicalName = resolvedName;
	    }
	} while (resolvedName != null);
	return canonicalName;
}
复制代码

2.2 从单例 Bean 缓存中获取 Bean

对应代码段如下:

//AbstractBeanFactory.java

//从缓存或实例工厂中获取 Bean 对象
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 + "'");
        }
    }
    // <x> 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}复制代码

  • 单列 Bean 再整个生命周期只会创建一次,并且把已经创建好的 Bean 存入缓存,这样下一次获取 Bean 时候直接从单列缓存中获取
  • <x> 处,如果从缓存里面得到了 Bean 对象,还需调用 AbstractBeanFactory#getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) 来实例化 Bean,因为缓存中的 Bean 有可能是最原始的 Bean ,不一定是实例化了的 Bean

详细解析,见 《【Spring 源码】—— IoC 之加载 Bean:从单例缓存中获取单》

2.3 原型模式依赖检查

对应代码段如下:

//AbstractBeanFactory.java

//Spring 只处理单列模式下的循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
}复制代码

Spring 只处理单例模式下得循环依赖,对于原型模式的循环依赖直接抛出异常。主要原因还是在于,和 Spring 解决循环依赖的策略有关。

  • 单列( Singleton )模式:Spring 再创建 Bean 的时候并不是等 Bean 完全创建完成后才会把 Bean 添加到缓存中,而是不等 Bean 创建完成就会将创建的 Bean 的 ObjectFactory 提早放在缓存中,这样一旦下一个 Bean 创建的时候需要依赖 Bean 时直接使用 ObjectFactory
  • 原型( Prototype )模式:没法使用缓存,循环依赖无法处理

详细解析,见 《【Spring 源码】—— IoC 之加载 Bean:parentBeanFactory 与依赖处理》

2.4 从 parentBeanFactory 获取 Bean

对应代码段如下:

// AbstractBeanFactory.java

// 如果当前容器中没有找到,则从父类容器中加载
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(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);
    }
}复制代码

如果当前容器中没有相对应的 BeanDefinition 对象,则会尝试从父容器中加载,然后递归调用 getBean(...) 方法。

详细解析,见 《【Spring 源码】—— IoC 之加载 Bean:parentBeanFactory 与依赖处理》

2.5 指定的 Bean 标记为已经创建或即将创建

对应代码段如下:

// AbstractBeanFactory.java

// 如果不是仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
    markBeanAsCreated(beanName);
}复制代码

详细解析,见 《【Spring 源码】—— IoC 之加载 Bean:parentBeanFactory 与依赖处理》

2.6 获取 BeanDefinition

对应代码段如下:

// AbstractBeanFactory.java

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

..todo


转载于:https://juejin.im/post/5ce4ed22e51d4510624f971c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值