Fork me on GitHub

Spring IOC 容器源码分析 - getBean调用方法解析(二)

1.getObjectForBeanInstance方法


 

/*
 * 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果
 * sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的
 * bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回
 * 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
 */
 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
getObjectForBeanInstance方法
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        // 如果 name 以 & 开头,但 beanInstance 却不是 FactoryBean,则认为有问题。
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
        }

        /*
         * 表明 beanInstance 是一个普通的bean,直接返回beanInstance
         */
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }

        Object object = null;
        if (mbd == null) {
            /*
             * 若 BeanDefinition 为 null,则从缓存中加载 Bean 对象
             */
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // 经过前面的判断,到这里可以保证 beanInstance 是 FactoryBean 类型的,所以可以进行类型转换
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // containsBeanDefinition 检测 beanDefinitionMap 也就是在所有bean配置项已经加载的类中
            // 检测是否定义 beanName
            if (mbd == null && containsBeanDefinition(beanName)) {
                // 将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition,
                // 如果指定 BeanName 是子 Bean 的话同时会合并父类的相关属性
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            // 是否是用户定义的,而不是应用程序本身定义的
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 核心处理方法,使用 FactoryBean 获得 Bean 对象
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }
getObjectFromFactoryBean方法
    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        /*
         * FactoryBean 也有单例和非单例之分,针对不同类型的 FactoryBean,这里有两种处理方式:
         *   1. 单例 FactoryBean 生成的 bean 实例也认为是单例类型。需放入缓存中,供后续重复使用
         *   2. 非单例 FactoryBean 生成的 bean 实例则不会被放入缓存中,每次都会创建新的实例
         */

        // <1> 为单例模式且缓存中存在
        if (factory.isSingleton() && containsSingleton(beanName)) {
            synchronized (getSingletonMutex()) {
                // <1.2> 从缓存中获取指定的 factoryBean
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    // 为空,则从 FactoryBean 中获取对象 去调用BeanFactory的getObject方法
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    // 从缓存中获取
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        // <1.3> 需要后续处理
                        // shouldPostProcess 等价于上一个方法中的 !synthetic,用于表示是否应用后置处理
                        if (shouldPostProcess) {
                            // 若该 Bean 处于创建中,则返回非处理对象,而不是存储它
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            // 单例 Bean 的前置处理  方法,用于添加标志,当前 bean 正处于创建中,用于支持类的循环引用
                            beforeSingletonCreation(beanName);
                            try {
                                // 对从 FactoryBean 获取的对象进行后处理
                                // 生成的对象将暴露给 bean 引用  涉及到BeanPostProcessor,去调用了后置处理
                                object = postProcessObjectFromFactoryBean(object, beanName);
                                //以上两个方法 他们记录着 Bean 的加载状态,是检测当前 Bean 是否处于创建中的关键之处,对解决 Bean 循环依赖起着关键作用。
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                            finally {
                                // 单例 Bean 的后置处理
                                afterSingletonCreation(beanName);
                            }
                        }
                        // 这里的 beanName 对应于 FactoryBean 的实现类, FactoryBean 的实现类也会被实例化,并被缓存在 singletonObjects 中
                        if (containsSingleton(beanName)) {
                            // FactoryBean 所创建的实例会被缓存在 factoryBeanObjectCache 中,供后续调用使用
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
        }
        // 获取非单例实例
        else {
            // 从工厂类中获取实例
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (shouldPostProcess) {
                try {
                    // 应用后置处理
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }

 

2.createBean方法


  该方法是作为一个匿名内部类传入了getSingletion方法中。我们先来看看这个方法。给方法的在AbstractAutowireCapableBeanFactory中被实现。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

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

        // 解析 bean 的类型
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        try {
            // 处理 lookup-method 和 replace-method 配置,Spring 将这两个配置统称为 override method
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // 实例化的前置处理
            // 给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例
            // AOP 的功能就是基于这个地方
            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 {
            //创建 Bean 对象
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }

主流程

  • 解析指定 BeanDefinition 的 class 属性。
  • 处理 override 属性。
  • 实例化的前置处理。
  • 创建 Bean 对象。

 

2.1.resolveBeanClass 解析指定 BeanDefinition 的 class

  • #resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch) 方法,主要是解析 bean definition 的 class 类,并将已经解析的 Class 存储在 bean definition 中以供后面使用。
  • 如果解析的 class 不为空,则会将该 BeanDefinition 进行设置到 mbdToUse 中。这样做的主要目的是,因为动态解析的 class 是无法保存到共享的 BeanDefinition 中。

2.2.prepareMethodOverrides方法

    /**
     *
     * 当用户配置了 lookup-method 和 replace-method 时,Spring 需要对目标 bean 进行增强。
     * 在增强之前,需要做一些准备工作,也就是 prepareMethodOverrides 中的逻辑。
     *
     *
     * 在Spring容器中,单例模式的bean只会被创建一次,然后容器会缓存该单例bean的实例,等到第二次获取时,可以直接返回该bean的实例,
     * 而无需重新创建;原型模式的bean则是每次都会创建一个全新的bean,Spring容器并不会缓存该bean的实例以供下次使用。那么如果现在
     * 有一个单例模式的bean引用了一个原型模式的bean呢?我们不希望被引用的原型模式bean被缓存,那么这个时候就需要用到lookup-method注入。
     *
     * replaced-method
     * 主要作用就是替换方法体及其返回值
     * <!-- ====================replace-method属性注入begin==================== -->
     * <bean id="replaceDog" class="com.lyc.cn.day05.replaceMethod.ReplaceDog"/>
     * <bean id="originalDog" class="com.lyc.cn.day05.replaceMethod.OriginalDog">
     *         <replaced-method name="sayHello" replacer="replaceDog"/>
     * </bean>
     * <!-- ====================replace-method属性注入end==================== -->
     */
    public void prepareMethodOverrides() throws BeanDefinitionValidationException {
        // Check that lookup methods exists.
        if (hasMethodOverrides()) {
            Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
            synchronized (overrides) {
                // 循环处理每个 MethodOverride 对象
                for (MethodOverride mo : overrides) {
                    prepareMethodOverride(mo);
                }
            }
        }
    }
    protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        // 获取方法名为 mo.getMethodName() 的方法数量,当方法重载时,count 的值就会大于1
        int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
        // count = 0,表明根据方法名未找到相应的方法,此时抛出异常
        if (count == 0) {
            throw new BeanDefinitionValidationException(
                    "Invalid method override: no method with name '" + mo.getMethodName() +
                    "' on class [" + getBeanClassName() + "]");
        }
        // 若 count = 1,表明仅存在已方法名为 mo.getMethodName(),这意味着方法不存在重载
        else if (count == 1) {
            // 方法不存在重载,则将 overloaded 成员变量设为 false
            mo.setOverloaded(false);
        }
    }

2.3.resolveBeforeInstantiation实例化前置处理

    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        // 检测是否解析过,mbd.beforeInstantiationResolved 的值在下面的代码中会被设置
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    // 应用前置处理
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            // 设置 mbd.beforeInstantiationResolved
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }
  • 这个方法核心就在于 applyBeanPostProcessorsBeforeInstantiation() 和 applyBeanPostProcessorsAfterInitialization() 两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。
  • 由于本文的主题是创建 bean ,关于 Bean 的增强处理后续说明。

2.4.doCreateBean 创建Bean

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        /*
         * BeanWrapper 是一个基础接口,由接口名可看出这个接口的实现类用于包裹 bean 实例。
         * 通过 BeanWrapper 的实现类可以方便的设置/获取 bean 实例的属性
         */
        BeanWrapper instanceWrapper = null;
        //单例模型,则从未完成的 FactoryBean 缓存中删除
        if (mbd.isSingleton()) {
            // 从缓存中获取 BeanWrapper,并清理相关记录
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            /*
             * 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
             * 创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。createBeanInstance
             * 中包含三种创建 bean 实例的方式:
             *   1. 通过工厂方法创建 bean 实例
             *   2. 通过构造方法自动注入(autowire by constructor)的方式创建 bean 实例
             *   3. 通过无参构造方法方法创建 bean 实例
             *
             * 若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用 CGLIB
             * 增强 bean 实例。关于这个方法
             */
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 此处的 bean 可以认为是一个原始的 bean 实例,暂未填充属性
        final Object bean = instanceWrapper.getWrappedInstance();
        // 包装的实例对象的类型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // 判断是否有后置处理
        // 如果有后置处理,则允许后置处理修改 BeanDefinition
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    // 后置处理修改 BeanDefinition
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        /*
         * 解决单例模式的循环依赖
         * earlySingletonExposure 是一个重要的变量,这里要说明一下。该变量用于表示是否提前暴露
         * 单例 bean,用于解决循环依赖。earlySingletonExposure 由三个条件综合而成,如下:
         *   条件1:mbd.isSingleton() - 表示 bean 是否是单例类型
         *   条件2:allowCircularReferences - 是否允许循环依赖
         *   条件3:isSingletonCurrentlyInCreation(beanName) - 当前 bean 是否处于创建的状态中
         *
         * earlySingletonExposure = 条件1 && 条件2 && 条件3
         *                        = 单例 && 是否允许循环依赖 && 是否存于创建状态中。
         */
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            // 提前将创建的 bean 实例加入到 singletonFactories 中
            // 这里是为了后期避免循环依赖
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // 开始初始化 bean 实例对象
        Object exposedObject = bean;
        try {
            // 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性
            // 则会递归初始依赖 bean
            populateBean(beanName, mbd, instanceWrapper);
            /*
             * 调用初始化方法
             * 进行余下的初始化工作,详细如下:
             * 1. 判断 bean 是否实现了 BeanNameAware、BeanFactoryAware、
             *    BeanClassLoaderAware 等接口,并执行接口方法
             * 2. 应用 bean 初始化前置操作
             * 3. 如果 bean 实现了 InitializingBean 接口,则执行 afterPropertiesSet
             *    方法。如果用户配置了 init-method,则调用相关方法执行自定义初始化逻辑
             * 4. 应用 bean 初始化后置操作
             *
             * 另外,AOP 相关逻辑也会在该方法中织入切面逻辑,此时的 exposedObject 就变成了
             * 一个代理对象了
             */
            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);
            }
        }
        //循环依赖处理
        if (earlySingletonExposure) {
            // 获取 earlySingletonReference
            Object earlySingletonReference = getSingleton(beanName, false);
            // 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
            if (earlySingletonReference != null) {
                // 若 initializeBean 方法未改变 exposedObject 的引用,则此处的条件为 true。
                // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
                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.");
                    }
                }
            }
        }

        //注册 bean
        try {
            // 注册销毁逻辑
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

细节后续解析

posted @ 2020-04-14 16:25  啊慌  阅读(338)  评论(0)    收藏  举报