Spring IoC源码学习:createBean 详解(上)

本文深入解析Spring IoC在`createBean`过程中的构造函数自动装配,涵盖代码块1至7的关键步骤,包括InstantiationAwareBeanPostProcessor的处理、构造函数的选择和依赖解析等。
摘要由CSDN通过智能技术生成

微信搜索【程序员囧辉】,关注这个坚持分享技术干货的程序员。

目录

Spring IoC源码学习全系列

前言

正文

createBean

代码块1:resolveBeforeInstantiation

代码块2:applyBeanPostProcessorsBeforeInstantiation

代码块3:doCreateBean

代码块4:createBeanInstance

代码块4.5:determineConstructorsFromBeanPostProcessors

代码块5:autowireConstructor

代码块6:resolveConstructorArguments

代码块7:createArgumentArray

代码块8:resolveAutowiredArgument

代码块9:resolveDependency

代码块10:doResolveDependency

代码块11:findAutowireCandidates

代码块12:isAutowireCandidate

代码块13:isAutowireCandidate

代码块14:isAutowireCandidate

代码块15:addCandidateEntry

代码块16:determineAutowireCandidate

代码块17:determinePrimaryCandidate

代码块18:determineHighestPriorityCandidate

代码块19:storeCache

总结

相关文章


Spring IoC源码学习全系列

小白也看得懂的 Spring IoC 核心流程介绍

Spring IoC源码学习:总览

Spring IoC源码学习:ApplicationContext 刷新前的配置

Spring IoC源码学习:obtainFreshBeanFactory详解

Spring IoC源码学习:parseDefaultElement详解

Spring IoC源码学习:parseCustomElement详解

Spring IoC源码学习:context:component-scan 节点详解

Spring IoC源码学习:invokeBeanFactoryPostProcessors详解

Spring IoC源码学习:registerBeanPostProcessors详解

Spring IoC源码学习:finishBeanFactoryInitialization详解

Spring IoC源码学习:getBean详解

Spring IoC源码学习:createBean详解(上)

Spring IoC源码学习:createBean详解(下)

Spring IoC源码学习:@Autowire 详解

Spring IoC源码学习:finishRefresh 详解

 

前言

接着 Spring IoC:getBean详解,我们继续解析获取 bean 实例里的核心内容:创建 bean 实例。

 

正文

首先,我们进入 createBean 方法。

 

createBean

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, 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.
    // 1.解析beanName对应的Bean的类型,例如:com.joonwhee.open.demo.service.impl.UserServiceImpl
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        // 如果resolvedClass存在,并且mdb的beanClass类型不是Class,并且mdb的beanClass不为空(则代表beanClass存的是Class的name),
        // 则使用mdb深拷贝一个新的RootBeanDefinition副本,并且将解析的Class赋值给拷贝的RootBeanDefinition副本的beanClass属性,
        // 该拷贝副本取代mdb用于后续的操作
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides.
    try {
        // 2.验证及准备覆盖的方法(对override属性进行标记及验证)
        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.
        // 3.实例化前的处理,给InstantiationAwareBeanPostProcessor一个机会返回代理对象来替代真正的bean实例,达到“短路”效果
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        // 4.如果bean不为空,则会跳过Spring默认的实例化过程,直接使用返回的bean
        if (bean != null) {
            return bean;
        }
    } catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }
    // 5.创建Bean实例(真正创建Bean的方法)
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");
    }
    // 6.返回创建的Bean实例
    return beanInstance;
}

3.实例化前的处理,给 InstantiationAwareBeanPostProcessor 一个机会返回代理对象来替代真正的 bean 实例,从而跳过 Spring 默认的实例化过程,达到“短路”效果,见代码块1详解

5.创建 bean 实例,见代码块3详解

 

代码块1:resolveBeforeInstantiation

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        // 1.mbd不是合成的,并且BeanFactory中存在InstantiationAwareBeanPostProcessor
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            // 2.解析beanName对应的Bean实例的类型
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 3.实例化前的后置处理器应用(处理InstantiationAwareBeanPostProcessor)
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    // 4.如果返回的bean不为空,会跳过Spring默认的实例化过程,
                    // 所以只能在这里调用BeanPostProcessor实现类的postProcessAfterInitialization方法
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        // 5.如果bean不为空,则将beforeInstantiationResolved赋值为true,代表在实例化之前已经解析
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

3.实例化前的后置处理器应用,见代码块2详解

4.实例化后的后置处理器应用,见 Spring IoC:getBean详解 中的代码块4

 

代码块2:applyBeanPostProcessorsBeforeInstantiation

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    // 1.遍历当前BeanFactory中的BeanPostProcessor
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        // 2.应用InstantiationAwareBeanPostProcessor后置处理器,允许postProcessBeforeInstantiation方法返回bean对象的代理
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 3.执行postProcessBeforeInstantiation方法,在Bean实例化前操作,
            // 该方法可以返回一个构造完成的Bean实例,从而不会继续执行创建Bean实例的“正规的流程”,达到“短路”的效果。
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                // 4.如果result不为空,也就是有后置处理器返回了bean实例对象,则会跳过Spring默认的实例化过程
                return result;
            }
        }
    }
    return null;
}

在实例化之前执行 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法,该方法可以返回 bean 实例的代理,从而跳过 Spring 默认的实例化过程。

 

代码块3:doCreateBean

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

    // Instantiate the bean.
    // 1.新建Bean包装类
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 2.如果是FactoryBean,则需要先移除未完成的FactoryBean实例的缓存
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 3.根据beanName、mbd、args,使用对应的策略创建Bean实例,并返回包装类BeanWrapper
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 4.拿到创建好的Bean实例
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    // 5.拿到Bean实例的类型
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                // 6.应用后置处理器MergedBeanDefinitionPostProcessor,允许修改MergedBeanDefinition,
                // Autowired注解正是通过此方法实现注入类型的预解析
                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.
    // 7.判断是否需要提早曝光实例:单例 && 允许循环依赖 && 当前bean正在创建中
    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");
        }

        // 8.提前曝光beanName的ObjectFactory,用于解决循环引用
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                // 8.1 应用后置处理器SmartInstantiationAwareBeanPostProcessor,允许返回指定bean的早期引用,若没有则直接返回bean
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // Initialize the bean instance.  初始化bean实例。
    Object exposedObject = bean;
    try {
        // 9.对bean进行属性填充;其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean实例
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            // 10.对bean进行初始化
            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) {
        // 11.如果允许提前曝光实例,则进行循环依赖检查
        Object earlySingletonReference = getSingleton(beanName, false);
        // 11.1 earlySingletonReference只有在当前解析的bean存在循环依赖的情况下才会不为空
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                // 11.2 如果exposedObject没有在initializeBean方法中被增强,则不影响之前的循环引用
                exposedObject = earlySingletonReference;
            } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                // 11.3 如果exposedObject在initializeBean方法中被增强 && 不允许在循环引用的情况下使用注入原始bean实例
                // && 当前bean有被其他bean依赖

                // 11.4 拿到依赖当前bean的所有bean的beanName数组
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    // 11.5 尝试移除这些bean的实例,因为这些bean依赖的bean已经被增强了,他们依赖的bean相当于脏数据
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        // 11.6 移除失败的添加到 actualDependentBeans
                        actualDependentBeans.add(dependentBean);
                    }
                }

                if (!actualDependentBeans.isEmpty()) {
                    // 11.7 如果存在移除失败的,则抛出异常,因为存在bean依赖了“脏数据”
                    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.
    try {
        // 12.注册用于销毁的bean,执行销毁操作的有三种:自定义destroy方法、DisposableBean接口、DestructionAwareBeanPostProcessor
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    } catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员囧辉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值