(四)BeanFactory初始化Singleton的实现细节

14 篇文章 2 订阅
8 篇文章 1 订阅

1.介绍

查看ApplicationContext的启动以及初始化部分的代码时,发现最终实现对象创建以及所有非懒加载的单例对象整体初始化,都是通过DefaultListableBeanFacotry来实现的
其中对象创建是通过beanFactory.getBean(xxx)来实现,而整体初始化是通过beanFactory.preInstantiateSingletons();来实现,
下面针对这两大接口,查看其实现细节。

2.BeanFacotry类图

这里写图片描述

2.beanFacotry创建对象的细节

创建对象是在AbstractBeanFacotry中实现的。
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    @Override
    public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
        return doGetBean(name, requiredType, null, false);
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return doGetBean(name, null, args, false);
    }
    public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
            throws BeansException {

        return doGetBean(name, requiredType, args, false);
    }
    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;

        // Eagerly check singleton cache for manually registered singletons.
        // 检查单例对象缓存,如果有通过registerSingleton(String beanName, Object singletonObject)的单例对象,也是注册到单例缓存中的
        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 + "'");
                }
            }
            //这里是实现FactoryBean的约定,获取对应factory.getObject()的Bean实例
            //(如果beanName前加&则返回一个FactoryBean的引用)。具体细节下面详细看
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            // 对于prototype的实例创建,spring是借助ThreadLocal来设置一个Set 来实现类似于单例对象的循环依赖检查的
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            // 优先委托父容器来获取Bean实例
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                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 {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

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

            try {
                //这里获取该bean的BeanDefination,如果是父容器中包含对应的BeanDefinition则通过子容器中的去override
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                //检查Definition(这里主要是检查是否为abstract标记的Definition不可创建)
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                // 保证要实例化的对象依赖于的所有对象要先进行实例化(比如在启动前的一些静态依赖项或者数据库准备等)
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        //这里检查对象循环依赖于对方的情况(比如A实例创建依赖于B、C、D,而在创建C时发现C又依赖于A实例的存在,这样就没办法创建实例了。)
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        //将依赖关系注册到依赖列表中,便于后续实例创建时的循环依赖检查
                        registerDependentBean(dep, beanName);
                        //这里进行递归创建依赖对象
                        getBean(dep);
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    //单例对象实现,如果已经创建完毕直接从单例缓存中取,如果是初次访问才会调用ObjectFactory触发createBean创建实例。
                    //在创建对象之前 会将当前要创建的对象先添加到singletonsCurrentlyInCreation这个Set中,同时能起到
                    //判断循环依赖注入的问题。
                    //比如A实例的创建需要通过构造器注入B实例,这时会触发B实例的getBean(b) 来创建B的实例,
                    //在创建B的过程中发现B 的构造器需要注入A的实例,而这时 又会进行getBean(a) 这时A实例已经存在于
                    //singletonsCurrentlyInCreation这个Set中,在创建前会先添加进去,如果添加失败,则表示存在循环注入
                    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.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    //通过上面创建出来的对象可能是FactoryBean 这里根据需要进行获取目标对象
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    //如果是prototype类型的对象,则每次都通过createBean创建新的实例
                    Object prototypeInstance = null;
                    try {
                        //prototype类型的对象也会有循环引用的问题,在上面
                        //isPrototypeCurrentlyInCreation(String beanName)判断过了,
                        //这里实现的是维护ThreadLocal中的多例对象,用来循环引用的检查,防止死递归。
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        //创建完毕,清除ThreadLocal中当前创建的beanName
                        afterPrototypeCreation(beanName);
                    }
                    //通过上面创建出来的对象可能是FactoryBean 这里根据需要进行获取目标对象
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    //这里是其它scope的实现,比如request scope是每次请求是创建对象放到request中、、、
                    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来获取对应scope的实例,比如request scope如果当前request中已存在对应对象,直接返回,不存在才调用ObjectFactory
                        //触发createBean创建实例
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        //通过上面创建出来的对象可能是FactoryBean 这里根据需要进行获取目标对象
                        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;
            }
        }

        // Check if required type matches the type of the actual bean instance.
        // 当需要的类型 与创建出来的实例类型不一致时,通过容器中的设置的typeConverter来作类型转换
        // 如果没设置则使用SimpleTypeConverter 通过JavaBean的PropertyEditor + spring定义的 ConversionService 来实现类型转换
        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;
    }
总结:
    这个方法主要是实现了通过单例缓存来满足“单例对象”(这里的单例是spring保证bean容器中只有一份实例。),
    以及prototype和其他scope实现(通过ObjectFactory将createBean以及维护用来循环引用检查的Set封装给scope使用)
    并负责循环引用的检查,防止出现死递归。
    关于scope,基本的scope是单例 + 多实例,而其他的scope则是通过Scope接口来自定义到BeanFactory中,
    Object get(String name, ObjectFactory<?> objectFactory);而BeanFactory则是通过将ObjectFactory委托
    给Scope接口来获取对象,实现对象的scope自定义。
    这里关于工厂模式的妙用:IOC容器负责定义好对象创建的方式,然后具体的创建对象的动作委托给scope来实现,
    这样就可以很灵活的拓展各种scope。
    比如request scope的实现则是每次判断request中有没有对应的属性,没有则创建并设置到attribute中,这样就
    保证了每个request对应一个指定的对象。

2.1.创建对象的实现细节createBean(beanName, mbd, args);

该方法来自AbstractAutowireCapableBeanFactory,这里主要是实现对象的实例化以及构造器注入、setter注入等
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

    if (logger.isDebugEnabled()) {
        logger.debug("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    // 通过BeanDefinition解析出要创建的对象的Class
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    // 这里判断BeanDefinition只是指定了ClassName 将解析到的Class对象设置进去,以供下面实例化时直接使用
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides.
    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        // 通过实现通过BeanPostProcessor的子接口定义的InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
        // 来获取目标对象(如果BeanDefinition允许的话。),如果获取实例成功则调用beanProcessor.postProcessAfterInitialization(result, beanName)
        // 完成实例化回调
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        // 这里实现,通过构造器、工厂方法、Supplier、等实例化对象,下面查看细节
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException ex) {
        // A previously detected exception with proper bean creation context already...
        throw ex;
    }
    catch (ImplicitlyAppearedSingletonException ex) {
        // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}
doCreateBean(beanName, mbdToUse, args);方法的实现细节
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        //通过有参、无参构造器或者工厂方法来创建对象,并使用BeanWrapper进行包装创建出来的对象
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                // 这里调用BeanPostProcessors中类型为MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition的回调
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 这里只是实例化了当前对象,下面在populate属性时,可能会涉及到依赖当前对象的实例创建,而当前对象尚未初始化完毕
    // 为了能满足被后续对象的创建,这里将当前对象的引用暴露给SingletonBeanRegistry
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    // 执行对象初始化。(init)
    Object exposedObject = bean;
    try {
        // 这里进行属性注入(setter注入)、以及进行回调用来依赖检查注入BeanPostProcessor.postProcessPropertyValues(..)
        //(其中@Autowired 以及@Resource等注解是基于BeanPostProcessor系列回调实现的)
        populateBean(beanName, mbd, instanceWrapper);
        //这里进行BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
        //以及执行对象 init方法
        //并实现BeanPostProcessor.postProcessBeforeInitialization以及BeanPostProcessor.postProcessAfterInitialization
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    //如果是在initializeBean(..)过程中对前面实例化的对象作了改变,那么此时这个提前暴露出去的对象还被别的对象注入过了的话
    //就会导致不保证单例对象的唯一性了,这里就是负责检查这种情况存在的,如果存在这种情况,可以通过getBeanNamesOfType 的allowEagerInit设置为false
    //强制不使用earlyExposed的单例对象。
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    // 如果对象指定了destroy方法 或者 需要destroy 将此对象注册到disposable列表中(如果是基于其他scope的 注册到对应scope的 destroy回调中)
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}
总结:
    spring通过AbstractBeanFactory.getBean(..)创建bean的整个过程中,如果是singleton 会优先通过
    SingletonBeanRegistry.getSingleton(..)来获取单例对象,因此spring中的单例模式并不是使用设计
    模式中常用的方法来实现的,而是在集合中维护,并通过同步(synchronization)保证对象只会创建一份来实现的,
    如果不不存在,则会执行对象创建的逻辑,而由于spring提供的是一个IOC容器,不止于创建对象,还包括
    对象依赖、声明周期(init、destroy)管理以及对象各个阶段的回调拓展(BeanPostProcessor系列接口)
    等等

    由于在对象执行初始化之前,要将对象实例化、依赖注入完毕,因此就会有循环引用的问题。
    比如单例的循环依赖:
        A实例的初始化 在依赖于B对象的实例(不是构造器上的依赖关系,而是成员属性中的依赖关系,构造器这种依赖关系是无解的)
        class A{
            B b;
            //setter..
        }
        class B {
            A a;
            //setter..
        }
        这种关系在spring中的创建过程是:
        先根据A的无参构造器创建出A 在执行初始化方法前 会先进行getBean(B) 注入到A中,这时 会触发
        B对象的创建,而B在初始化方法前,也会注入A 这时getBean(A) 能获取到A实例的earlyExpose的一个引用,因此B注入成功
        这时B进行初始化完毕,A 注入成功,A初始化完毕。

        prototype类型的对象这样的循环依赖就比较容易了,最终会产生 (A1 -> B -> A2) 3个对象。而单例对象 由于只能存在2个对象
        所以才需要特殊处理一下来实现。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值