(4)Bean的加载

这里写图片描述

这里写图片描述

protected <T> T doGetBean(
        final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
        throws BeansException {

    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    /*检查缓存中或者实例工厂中是否有对应的实例
     *因为在创建单例bean的时候会存在依赖注入的情况,为了避免循环引用
     *Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光
     *即将ObjectFactory加入到缓存之中,一旦下一个bean创建的时候需要依赖上一个bean则直接
     *使用beanFactory 
    */
    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 + "'");
            }
        }
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // 原型类型的bean是不允许循环依赖的,所以Exception
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            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 {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dependsOnBean : dependsOn) {
                    if (isDependent(beanName, dependsOnBean)) {
                        throw new BeanCreationException("Circular depends-on relationship between '" +
                                beanName + "' and '" + dependsOnBean + "'");
                    }
                    registerDependentBean(dependsOnBean, beanName);
                    getBean(dependsOnBean);
                }
            }

            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        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;
                        }
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        }
                    });
                    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.
    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
        try {
            return getTypeConverter().convertIfNecessary(bean, requiredType);
        }
        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;
}

实际的doGetBean过程很复杂,拆成步骤来分析
1.转换对应的beanName

这里写图片描述

因为这里传入的参数可能是别名,也可能是FactoryBean,所以要进行一系列的解析,解析的内容包括:
去除FactoryBean的修饰符,也就是如果name=”&aa”,那么会首先去除&而使name=”aa”
取置顶alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B,如果A指向B,B又指向C则返回C

这里写图片描述

2.尝试从缓存中加载bean

这里写图片描述

这里写图片描述

这里写图片描述

默认allowEarlyReference是设置为true的
这个的作用是为了处理singleton bean的依赖注入的情况,在创建依赖的时候为了避免循环依赖,Spring创建bean的原则是不等bean创建完成就会将创建的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上一个bean,则直接使用ObjectFactory

注:定义bean的时候是可以指定scope的,默认是单例

先说一下各个缓存的作用:

这里写图片描述

singletonObjects:
用于保存BeanName和创建bean实例之间的关系,bean name -> bean instance
singletonFactories:
用于保存BeanName和创建bean的工厂之间的关系,bean name -> ObjectFactory
earlySingletonObjects:
也是保存BeanName和创建bean实例之间的关系,与SingletonObjects的不同之处在于,当一个实例bean被放到这里面后,那么当bean还在创建的过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用
registeredSingletons:
用来保存当前所有已注册的bean

在缓存之中没有拿到bean
这里写图片描述

3.Bean的实例化,如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。

强调:缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean。
切记

这里写图片描述

在getBean方法中,getObjectForBeanInstance是个高频率使用的方法,无论是从缓存中获得bean还是根据不同的scope策略加载bean。总之,得到bean的实例后要做的第一件事就是调用这个方法来检测一下正确性。
这里写图片描述

这里写图片描述

这里写图片描述

这里为什么会有&作为前缀?通常使用的FactoryBean也是直接用BeanName来获取的。
当使用&作为前缀的时候表示用户想要的是直接获取FactoryBean工厂实例而不是FactoryBean.getObject()对应的实例。

处理FactoryBean

这里写图片描述

先是从缓存中拿FactoryBean,如果拿不到真正的获取FactoryBean的逻辑委托给getObjectFromFactoryBean
这里写图片描述

这里还是就判定一下是否单例,是单例需要保证全局唯一,并且使用缓存。实际的创建逻辑在doGetObjectFromFactoryBean之中
这里写图片描述
终于看到了factory.getObject()
不过在调用factory.getObject()获取bean之后并没有直接返回bean,还有下面一部分:
这里写图片描述
调用的是AbstractAutowireCapableBeanFactory之中的postProcessObjectFromFactoryBean()
这里写图片描述
这里写图片描述
这里是调用了后处理器,这里可以了解Spring获取bean的规则中的一条:
尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理,在实际的开发工程中大可以针对此特性设计自己的业务逻辑。

同时说一下applyBeanPostProcessorsBeforeInitialization
这里写图片描述
暂时还没有看到调用的时机

到此全部是从缓存中寻找是否有singletonbean,已经从FactoryBean之中获取bean

如果都失败了,那么进入else
这里写图片描述
只有在单例情况下才会尝试解决循环依赖,如果A依赖B,B依赖A,那么造成循环依赖,引起BeanCurrentlyInCreationException

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值