Spring源码浅析之Bean的创建(前篇)

在Spring容器中,Bean的生命周期都是交由BeanFactory接口以及它的实现类处理的。
AbstractBeanFactory是BeanFactory接口的一个默认抽象实现类,他实现了BeanFactory接口的方法,并在此基础上进行了扩展。
Spring规定BeanFactory接口的实现类应该能尽可能的支持bean的标准生命周期。
一个Bean的标准生命周期如下(图片侵删):
这里写图片描述
我们也可以在Spring的官方文档和源码的注释中看到更为精确的Bean的标准生命周期以及它的顺序。
而一个Bean的创建过程将会贯穿除了destroy的整个生命周期(但非规定的全部)。

AbstractBeanFactory
本文将分两篇。前篇从AbstractBeanFactory类入手,简单的讲一讲Spring容器中Bean的部分创建过程。

doGetBean
首先来看AbstractBeanFactory类中的doGetBean方法,它是该类中一系列public的getBean方法的内部方法。该方法会根据Bean的类名、Class和构造参数等参数返回特定的Bean,这些Bean可以来自不同的配置源配置的Bean或者Spring容器本身的Bean。并且,根据是否已经注册Bean和Bean的类型选择是否创建该Bean,具体源码如下(代码较长,省略了其中的日志输出代码)。

// 传入bean类名和bean的Class类型以及构造参数
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        // 将类名转化为全限定名
        final String beanName = transformedBeanName(name);
        Object bean;

        // 检查缓存中是否已经存在注册的单例bean
        // (单例bean能提前注册消除bean注册的循环引用问题)
        Object sharedInstance = getSingleton(beanName);
        // 如果存在则获取该bean
        if (sharedInstance != null && args == null) {
            // 省略部分日志(单例bean是否已在创建中)
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        // 如果不存在
        else {
            // 首先判断该bean是否在正在创建中或循环引用
            // 判断原型bean是否在创建中,若是则抛出异常
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 检查父BeanFactory中,该bean的BeanDefine是否已经注册
            // parentBeanFactory为该bean目前对应的BeanFactory的父BeanFactory
            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 在父BeanFactory中找不到该bean的BeanDefine
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 继续检查父类BeanFactory的BeanDefine
                String nameToLookup = originalBeanName(name);
                // 已经到了AbstractBeanFactory类,继续检查
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                // 分情况,有参无参作不同检查
                else if (args != null) {
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                // 获取并检查bean的BeanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 保证bean依赖的bean已经初始化
                // 从BeanDefinition获取依赖的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 + "'");
                        }
                        // 注册需要依赖的bean
                        registerDependentBean(dep, beanName);
                        try {
                            // 创建(初始化)该Bean
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // 创建bean.
                // 如果是单例的bean
                if (mbd.isSingleton()) {
                    // 创建bean(前面已经检查过还未注册过该bean)
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            // 创建bean的方法,后篇会详述
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // 出现异常则显式注销该bean
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    // 获取该bean实例
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                // 如果是原型的bean
                else if (mbd.isPrototype()) {
                    // 直接创建新的实例
                    Object prototypeInstance = null;
                    try {
                        // 将bean名存入原型bean的“正在创建”缓存set中
                        beforePrototypeCreation(beanName);
                        // 创建bean
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        // 清除该bean的“正在创建”缓存
                        afterPrototypeCreation(beanName);
                    }
                    // 获取该bean的实例
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                // 其他情况
                else {
                    // 从BeanDefinition中获取bean的scope
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    // scope为空则抛出异常
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        // 默认按原型bean处理
                        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;
            }
        }

        // 确认bean的实例类型与所需的类型是否一致
        // 如果不是则需要转换
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                // 强转bean类型
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                // 失败则抛出异常
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            // 失败则抛出异常
            catch (TypeMismatchException ex) {
                // 输出日志并抛出异常
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        // 返回bean实例
        return (T) bean;
    }

从上面的源码中可以看到,Spring获取bean的整个过程主要分为两步:
1.如果已经注册且为单例的bean,直接从缓存中获取实例。
2.如果没有注册或为其他形式的bean,先检查是否正在创建,再根据不同类型创建相应bean,最后将获取的object实例强转为相应类型的bean。

重要方法
下面我们来看几个源码中比较重要的方法
在这之前,我们先来看看AbstractBeanFactory的类图
这里写图片描述
其中FactoryBeanRegistrySupport类主要用于bean的注册和创建。
源码中频繁出现了两个方法,getSingleton和getObjectForBeanInstance。
getSingleton方法是DefaultSingletonBeanRegistry类中的几个重载方法,主要用于单例bean的创建注册和获取。
getObjectForBeanInstance方法是AbstractBeanFactory类内的方法,调用的内部方法也来自继承的FactoryBeanRegistrySupport类,它能从factoryBeanObjectCache缓存中获取到已经注册的bean实例。本文不对它进行过多描述,感兴趣的小伙伴可以直接看源码。
下面我们主要来看看getSingleton方法。

getSingleton
DefaultSingletonBeanRegistry中有三个重载的getSingleton方法,其中两个能够返回已经注册的bean,且能返回正在创建的bean。
这个措施能解决bean注册时会遇到的循环引用问题。两个方法的代码如下:

    @Override
    @Nullable
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }


    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 从缓存中获取单例bean
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果获取不到但又是正在创建的bean则从earlySingletonObjects中获取
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                // 从earlySingletonObjects缓存中获取
                singletonObject = this.earlySingletonObjects.get(beanName);
                // 如果获取不到且允许提前引用(默认true),则将bean存于earlySingletonObjects中
                if (singletonObject == null && allowEarlyReference) {
                    // singletonFactory是注册的单例工厂
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        // 将bean以beanName的形式存入earlySingletonObjects缓存
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

从上面的代码我们可以看到,这两个重载的getSingleton方法不参与bean的创建,它只从缓存中拿。且当bean处于创建状态时,能够提前暴露该bean。这能解决单例bean之间的循环引用问题:
当A依赖B,B同时依赖A时,A在创建时需要B已经创建,而B创建时也需要A已经创建。如果没有提前引用的措施,AB在创建时会陷入无限等待对方的情况中

另一个重载的getSingleton方法则可以创建bean,代码如下(简化了日志输出代码):

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        // 检查类名是否为空
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized (this.singletonObjects) {
            // 从缓存中获取bean实例
            Object singletonObject = this.singletonObjects.get(beanName);
            // 如果不存在
            if (singletonObject == null) {
                // 如果bean的factory正在注销则报错
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                // 将bean加入“正在创建”缓存中
                beforeSingletonCreation(beanName);
                // 初始化参数
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    // 创建bean,AbstractBeanFactory类中采用lambda的的方式实现,实际的核心是AbstractBeanFactory的createBean方法
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    // 将bean移除“正在创建”缓存
                    afterSingletonCreation(beanName);
                }
                // 完成注册,将bean加入已注册beans中,移除中间缓存
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

从上面的代码中我们可以看出,这个重载的getSingleton方法相较于其他两个方法,多了创建bean的步骤。这里不做过多解释。

总结
通过上述源码,我们大致可以看出Spring容器中bean的创建过程。与此同时,Spring还用了提前引用的方式,来解决bean创建过程中的循环引用死锁问题。
创建bean时的一个核心方法是createBean,它是AbstractBeanFactory类中的一个抽象方法,AbstractBeanFactory的子类将实现这个方法。DefaultListableBeanFactory类和AbstractAutowireCapableBeanFactory类是AbstractBeanFactory类的两个子类。之后的博客中我会从这两个类入手,继续从源码的角度简单分析一下这个createBean方法。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值