我是靠谱客的博主 唠叨电源,最近开发中收集的这篇文章主要介绍解析BeanFactory的核心方法——getBean,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本系列源码都是基于spring-4.3.8版本之上,其他版本略有差异,但总体的核心思想相同。同时,为了使贴出的源代码尽可能的紧凑,可能会删去一些异常捕获、日志输出等代码。若文中存在纰漏错误,欢迎指正。

先看一下BeanFactory中定义的所有getBean方法

    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

以上五个getBean方法中,所有带beanName参数的方法都在AbstractBeanFactory中实现了,其余的两个也在DefaultListableBeanFactory中实现了。

AbstractBeanFactory中的getBean

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

    @Override
    public <T> T getBean(String name, 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, Class<T> requiredType, Object... args) throws BeansException {
        return doGetBean(name, requiredType, args, false);
    }

DefaultListableBeanFactory中的getBean

    @Override
    public <T> T getBean(Class<T> requiredType) throws BeansException {
        return getBean(requiredType, (Object[]) null);
    }

    @Override
    public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
        NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
        if (namedBean != null) {
            return namedBean.getBeanInstance();
        }
        BeanFactory parent = getParentBeanFactory();
        if (parent != null) {
            return parent.getBean(requiredType, args);
        }
        throw new NoSuchBeanDefinitionException(requiredType);
    }

可以看出除了DefaultListableBeanFactory#getBean(Class<T> requiredType, Object... args)之外,其他的方法都是通过直接通过AbstractBeanFactory#doGetBean获取bean的。

那么我们再重新看一下这个看似不同的getBean方法

    public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException {
        // 调用当前类的resolveNamedBean获取NamedBeanHolder
        NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, (Object[]) null);
        if (namedBean != null) {
            return namedBean;
        }
        // 若获取不到,则获取parentBeanFactory,以parentBeanFactory#resolveNamedBean获取NamedBeanHolder
        BeanFactory parent = getParentBeanFactory();
        if (parent instanceof AutowireCapableBeanFactory) {
            return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType);
        }
        throw new NoSuchBeanDefinitionException(requiredType);
    }

看来关键还是得看DefaultListableBeanFactory#resolveNamedBean

    @SuppressWarnings("unchecked")
    private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
        Assert.notNull(requiredType, "Required type must not be null");
        // 以beanClass换取beanName,即通过该bean的类型从allBeanNamesByType中获取beanName
        // 候选者beanName数组
        String[] candidateNames = getBeanNamesForType(requiredType);

        if (candidateNames.length > 1) {
            List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);
            // 通过beanName获取BeanDefinition,且BeanDefinition#autowireCandidate为true即可加入候选组,该值默认即true
            for (String beanName : candidateNames) {
                if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
                    autowireCandidates.add(beanName);
                }
            }
            // 将经过筛选的候选者重新赋值到candidateNames
            if (!autowireCandidates.isEmpty()) {
                candidateNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
            }
        }

        // 候选者若只有一个,那直接以该beanName通过AbstractBeanFactory#getBean获取bean实例
        if (candidateNames.length == 1) {
            String beanName = candidateNames[0];
            // 依然是以beanName从AbstractBeanFactory#getBean获取bean实例
            return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
        }
        // 若候选者不止一个,则需要重新选举最合适的
        else if (candidateNames.length > 1) {
            Map<String, Object> candidates = new LinkedHashMap<String, Object>(candidateNames.length);
            for (String beanName : candidateNames) {
                if (containsSingleton(beanName)) {
                    // 依然是以beanName从AbstractBeanFactory#getBean获取bean实例
                    candidates.put(beanName, getBean(beanName, requiredType, args));
                } else {
                    candidates.put(beanName, getType(beanName));
                }
            }
            // 首先通过AbstractBeanDefinition#primary筛选候选者
            String candidateName = determinePrimaryCandidate(candidates, requiredType);
            if (candidateName == null) {
                // 若筛选失败,候选者都被淘汰时,再重新以Priority进行筛选候选者
                candidateName = determineHighestPriorityCandidate(candidates, requiredType);
            }
            if (candidateName != null) {
                Object beanInstance = candidates.get(candidateName);
                if (beanInstance instanceof Class) {
                    // 依然是以beanName从AbstractBeanFactory#getBean获取bean实例
                    beanInstance = getBean(candidateName, requiredType, args);
                }
                return new NamedBeanHolder<T>(candidateName, (T) beanInstance);
            }
            throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
        }

        return null;
    }

可以看出,该方法除了最后的返回null和抛出异常结束之外,其余的出口也依然是通过AbstractBeanFactory#getBean获取实例的,所以绕了半天,其本质依然是通过AbstractBeanFactory#doGetBean获取bean实例的。

因此所有的getBean只是通过不同的传参方式调用doGetBean,其本质上还是得通过AbstractBeanFactory#doGetBean获取bean实例的,所以看来重点就是这个doGetBean方法了。

    /**
     * {@link AbstractBeanFactory#getBean(String)}
     * {@link AbstractBeanFactory#getBean(String, Class)}
     * {@link AbstractBeanFactory#getBean(String, Object...)}
     * {@link AbstractBeanFactory#getBean(String, Class, Object...)}
     * {@link DefaultListableBeanFactory#getBean(Class)}
     * {@link DefaultListableBeanFactory#getBean(Class, Object...)}
     * AbstractBeanFactory中实现了大部分的getBean,剩余的在DefaultListableBeanFactory中实现
     * 而不论哪一种最终都是需要通过doGetBean获取bean实例
     */
    @SuppressWarnings("unchecked")
    protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args,
            boolean typeCheckOnly) throws BeansException {

        /**
         * 对name进行解析,主要做了两件事:
         * (1)将name开头的所有"&"去除,并赋值给beanName,如此一来,name负责处理与factoryBean有关的bean获取,
         * 而beanName则用来获取所有其他bean。
         * (2)以转换后的name调用SimpleAliasRegistry.canonicalName(String),以alias别名换取id
         */
        final String beanName = transformedBeanName(name);
        Object bean;

        /**
         * 尝试以singleton的方式调用DefaultSingletonBeanRegistry.getSingleton(String)获取bean,
         * 这个方法还会以allowEarlyReference=true即允许早期引用的形式继续调用getSingleton(String beanName,
         * boolean allowEarlyReference)。
         * 该方法会先从一级缓存singletonObjects以及二级缓存earlySingletonObjects中获取,
         * 若依然获取不到,由于allowEarlyReference=true,则会继续从三级缓存singletonFactories中获取objectFactorys,
         * 若获取到了就以objectFactory#getObject的方式获取bean。 执行过程可能是以下的几种情况:
         * 1、从一级缓存singletonObjects中获取bean,若获取到了说明获取的bean早就被创建好了,否则继续获取
         * 2、一级缓存未获取到,继续从二级缓存earlySingletonObjects中获取,若获取到了,说明该beanName虽然已被创建完毕,
         * 但还非完全实例化完毕(singletonsCurrentlyInCreation中必然存在该beanName),
         * 只是提早暴露了出来而已。(而之所以会在二级缓存earlySingletonObjects中,请看(3))
         * 3、一级、二级缓存中都未获取到,且allowEarlyReference=true的时候,从三级缓存singletonFactories中获取,
         * 获取到的是objectFactory,若获取到了,说明当前beanName正在创建中,尚未完全创建完毕,
         * 只是提前将自己的制造工厂——ObjectFactory暴露出来了而已,然后继续调用ObjectFactory#getObject获取bean,
         * 一般而言,这里的ObjectFactory#getObject都是在AbstractAutowireCapableBeanFactory.doCreateBean中添加的,
         * 且getObject方法是调用AbstractAutowireCapableBeanFactory.getEarlyBeanReference获取早期引用的。
         * 4、三级缓存中也没有获取到,说明当前bean尚未被加载过,方法执行完毕,doGetBean继续向下执行。
         */
        Object sharedInstance = getSingleton(beanName);
        /**
         * 根据之前的getSingleton(String)是否从缓存中获取到了bean决定如何执行:
         * 1、若获取到了,则继续调用AbstractBeanFactory.getObjectForBeanInstance判断该类是否实现了FactoryBean,
         * 若实现了则调用getObject获取bean,否则依然返回bean。 2、若未获取到则说明该bean尚未被初始化或者其根本就不是单例而是多例,继续执行下去
         */
        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 {
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 尝试获取父容器,并从父容器中获取bean
            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 若父容器存在,且当前容器不包含该beanName,则尝试从父容器获取bean
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 转化beanName,去除"&",并以alias别名换取id
                String nameToLookup = originalBeanName(name);
                // 从父容器获取bean
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                } else {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            /**
             * 用来标记当前bean是否已被创建完毕的方法,若当前bean尚未被创建,则执行完该方法,
             * 其就会被加入到AbstractBeanFactory.alreadyCreated中,表示该bean已被创建或即将被创建。
             * 根据doGetBean的第三个参数markBeanAsCreated决定是否执行该方法,
             * 目前的所有getBean方法都默认会将typeCheckOnly设置为false,即都会执行该方法。
             */
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                /**
                 * 获取合并后的本地BeanDefinition,
                 * 根据beanName从AbstractBeanFactory#mergedBeanDefinitions中获取RootBeanDefinition,
                 * 若获取不到,则调用DefaultListableBeanFactory.getBeanDefinition,从beanDefinitionMap中获取BeanDefinition,
                 * 获取不到就抛出NoSuchBeanDefinitionException,
                 * 否则就继续调用AbstractBeanFactory.getMergedBeanDefinition(String, BeanDefinition)
                 */
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                /**
                 * 获取该bean的依赖,若存在,则逐个以DefaultSingletonBeanRegistry.registerDependentBean添加到dependentBeanMap中
                 * 并通过AbstractBeanFactory.getBean(String)保证当前Bean依赖的Bean全部被初始化,所以递归getBean。
                 */
                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 + "'");
                        }
                        registerDependentBean(dep, beanName);
                        getBean(dep);
                    }
                }

                /**
                 * 若是单例,则调用DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>),
                 * 同时通过内部类的方式重写了ObjectFactory#getObject,
                 * 其会先从缓存DefaultSingletonBeanRegistry#singletonObjects中获取,
                 * 获取不到则说明该bean还未被实例化,以ObjectFactory#getObject继续获取该bean实例,
                 * 然后以匿名内部类的方式调用AbstractBeanFactory#createBean进行创建bean的操作,
                 * 实例化完成后,调用DefaultSingletonBeanRegistry#addSingleton将其放入缓存map-singletonObjects中,
                 * 这样之后调用就不会再创建了
                 */
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                return createBean(beanName, mbd, args);
                            } catch (BeansException ex) {
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    // 判断是否需要继续转化为FactoryBean获取bean
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                // 若是多例,则会直接调用上述AbstractBeanFactory#createBean直接创建bean。
                else if (mbd.isPrototype()) {
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    } finally {
                        afterPrototypeCreation(beanName);
                    }
                    // 判断是否需要继续转化为FactoryBean获取bean
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                /**
                 * 若均不是,则调用AbstractBeanDefinition.getScope()获取该bean的Scope,
                 * 而后重写Scope#getObject并调用Scope.get(String, ObjectFactory<?>)获取bean实例,
                 * 最终依然会调用刚才重写的getObject并调用createBean创建bean。
                 */
                else {
                    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 {
                        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);
                                }
                            }
                        });
                        // 判断是否需要继续转化为FactoryBean获取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,但是bean类型又与期待的类型不匹配时,调用TypeConverter#convertIfNecessary进行类型转换
        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;
    }

 

最后

以上就是唠叨电源为你收集整理的解析BeanFactory的核心方法——getBean的全部内容,希望文章能够帮你解决解析BeanFactory的核心方法——getBean所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部