3-Spring-Bean的实例化(一)

容器Bean实例化

上一节有提到过,在容器准备完成之后,初始化剩下所有的单例Bean(非延迟加载的) 。

finishBeanFactoryInitialization(beanFactory),查看源码可以知道,获取容器中所有的beanName依次调用AbstractBeanFactory#getBean(String name)方法触发Bean的实例化。

getBean

// AbstractBeanFactory.java
@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

内部调用 doGetBean(String name, final Class requiredType, Object[] args, boolean typeCheckOnly) 方法,其接受四个方法参数:

  • name :要获取 Bean 的名字
  • requiredType :要获取 bean 的类型
  • args :创建 Bean 时传递的参数。这个参数仅限于创建 Bean 时使用。
  • typeCheckOnly :是否为类型检查。

doGetBean

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    // 1. 根据指定的名称获取获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
    // 如果指定的是别名,则将别名转换为规范的Bean名称
    final String beanName = transformedBeanName(name);
    Object bean;
    // 2. 先从缓存中读取是否有已经被创建过的单例模式的Bean, 对于单例模式的Bean, 整个IOC容器中只创建一次
    // Eagerly check singleton cache for manually registered singletons.
    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 + "'");
            }
        }
        // 3. 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
        // 注意:BeanFactory是管理Bean的工厂, FactoryBean是创建对象的工厂Bean, 两者之间有区别
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    else {
        // 运行到这里, 说明缓存中没有我们想要的Bean
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // 4. 因为 Spring 只解决单例模式下的循环依赖, 所以在原型模式下如果存在循环依赖则会抛出异常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
        // 5. 获取当前容器的父容器
        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            // 解析指定Bean名称的原始名称
            String nameToLookup = originalBeanName(name);
            // 父类容器为 AbstractBeanFactory, 直接递归查找
            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);
            }
        }
        // 6. 创建的Bean是否需要进行类型验证
        if (!typeCheckOnly) {
            // 如果不需要, 将指定的bean标记为已经创建(或即将创建)
            markBeanAsCreated(beanName);
        }

        try {
            // 7. 从容器中获取 beanName 相应的 BeanDefinition 对象
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);
            // 8. 处理所依赖的Bean
            // 每个 bean 都不是单独工作的,它会依赖其他 bean,其他 bean 也会依赖它,对于依赖的 bean ,它会优先加载,所以在 Spring 的加载顺序中,在初始化某一个 bean 的时候首先会初始化这个 bean 的依赖。
            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                // 当前Bean有依赖的Bean
                for (String dep : dependsOn) {
                    // 循环依赖的情况
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 把被依赖的Bean注册给当前的Bean
                    registerDependentBean(dep, beanName);
                    try {
                        // 递归调用getBean方法,实例化当前Bean所依赖的Bean
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }
            // 9. 实例化Bean
            // Create bean instance.
            if (mbd.isSingleton()) { // 单例模式
                // 这里使用一个匿名内部类创建Bean实例对象
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        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);
            }

            else if (mbd.isPrototype()) { // 原型模式
                // It's a prototype -> create a new instance.
                // 原型模式每次都会创建一个新的对象
                Object prototypeInstance = null;
                try {
                    // 记录当前创建的原型对象
                    beforePrototypeCreation(beanName);
                    // 创建Bean
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    // beforePrototypeCreation 记录了当前创建的原型对象, 此时需要移除
                    afterPrototypeCreation(beanName);
                }
                // 获取Bean的实例对象
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
            else { 
                // 要创建的Bean既不是单例模式的也不是原型模式的
                // 这种方式在Web应用程序中比较常用, 如request、session、application等生命周期
                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);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }
    // 10. 检查需要的类型是否符合 bean 的实际类型
    // Check if required type matches the type of the actual bean instance.
    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.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.java
//  根据指定的名称获取获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
// 如果指定的是别名,则将别名转换为规范的Bean名称
final String beanName = transformedBeanName(name);

这里的name不一定就是beanName,有可能是bean的别名,也有可能是 FactoryBean ,所以这里通过 transformedBeanName(String name) 方法对 name 进行转换

// AbstractBeanFactory.java
protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

调用 BeanFactoryUtils#transformedBeanName(String name) 方法,是为了去除 FactoryBean 的修饰符 ,如果 name 以 “&” 为前缀,那么会去掉该 “&”,例如,name = "&studentService",则会是 beanName = "studentService"

// BeanFactoryUtils.java
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    // BeanFactory.FACTORY_BEAN_PREFIX = "&";
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    // computeIfAbsent 方法,分成两种情况:
    // 1. name未存在,则进行计算执行,并将结果添加到缓存
    // 2. name已存在,则直接返回。
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

transformedBeanNameCache主要是用来缓存name转换后的beanName,下次获取相同的name时可以直接从缓存中获取。

public String canonicalName(String name) {
    String canonicalName = name;
    String resolvedName;
    do {
        resolvedName = (String)this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    } while(resolvedName != null);

    return canonicalName;
}

主要是一个循环获取 beanName 的过程,例如,别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 C。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值