Spring源码(四):bean的创建

本节紧接上一篇,深入讨论一个标准bean在Spring中究竟是如何生成&销毁的(重点关注Spring对bean的构造方法、注入字段、各种扩展方法的处理,以及围绕整个bean的全生命周期,Spring留了那些扩展点给用户实现)。

一、创建bean

介绍了循环依赖以及Spring中循环依赖的处理方式后,我们继续之前的内容。当经历过resolveBeforeInstantiation方法后,程序有两个选择,如果创建了代理或者或重写InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法并在postProcessBeforeInstantiation方法中改变了bean,则直接返回就可以了,否则需要进行bean的创建。而这一常规bean的创建就是在doCreateBean中完成的。代码如下

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
   
   
    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
   
   
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
   
   
        // 根据指定的bean使用对应的策略创建新的实例:如工厂方法、构造方法自动注入、简单初始化
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
   
   
        if (!mbd.postProcessed) {
   
   
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            mbd.postProcessed = true;
        }
    }

    // 是否需要提早曝光:单例且允许循环依赖且当前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");
        }
        // 为了避免后期循环依赖,可以在bean初始化完成之前将创建创建实例的ObjectFactory加入工厂
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
   
   
            public Object getObject() throws BeansException {
   
   
                // 对bean再一次依赖引用
                // 其中我们熟知的AOP就是在这里将advice动态织入bean中,若没有则无需处理直接返回
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
   
   
        // 对bean进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖bean
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
   
   
            // 调用初始化方法,比如init-method
            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) {
   
   
        Object earlySingletonReference = getSingleton(beanName, false);
        // earlySingletonExposure只有当检测导游循环依赖的情况才不为空
        if (earlySingletonReference != null) {
   
   
            // 如果exposedObject没有在初始化方法中被改变,也就是没有被增强
            if (exposedObject == bean) {
   
   
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
   
   
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
   
   
                    // 检查依赖
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
   
   
                        actualDependentBeans.add(dependentBean);
                    }
                }
                // 因为bean创建后其所依赖的bean一定是已经创建完成的
                // actualDependentBeans不为空则标示当前bean创建后其依赖的bean却没有全部创建完,也就是存在循环依赖
                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.
    try {
   
   
        // 根据scope注册bean 
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
   
   
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

尽管日志与异常的内容非常重要,但是在阅读源码的时候似乎大部分人都会直接忽略。在此不深入探讨日志及异常的设计,我们看看整个方法的概要思路:

  • 如果是单例则需要先清除缓存。
  • 实例化bean,将BeanDefinition转换为BeanWrapper。

转换是一个复杂的过程,但是我们可以概括大致的功能,如下所示:

1.如果存在工厂方法则使用工厂方法进行初始化。

2.一个类有多个构造方法,每个构造方法都有不同的参数,所以需要根据参数锁定构造方法并进行初始化。

3.如果不存在工厂方法也不存在带有参数的构造方法,则使用默认的构造方法进行bean的实例化。

  • MergedBeanDefinitionPostProcessor的应用。

bean合并后的处理,Autowire注解正是通过此方法实现诸如类型的预解析。

  • 依赖处理。

在Spring中会有循环依赖的情况,例如当A中含有B的属性,而B中又含有A的属性时就会构成一个循环依赖,此时如果A和B都是单例,那么在Spring中处理的方式就是当创建B的时候,涉及自动注入A的步骤时,并不是直接再次创建A,而是通过方法缓存中的ObjectFactory来创建实例,这样就解决了循环依赖的情况。

  • 属性填充。将所有属性填充至bean的实例中。
  • 循环依赖检查。

之前有提到过,在Spring中解决循环依赖只对单例有效,而对于prototype和bean,Spring没有好的解决办法,唯一要做的就是抛出异常。在这个步骤里面会检测已经加载的bean是否已经出现循环依赖,并判断是否需要抛出异常。

  • 注册DisposableBean。

如果配置了destroy-method,这里需要注册以便于在销毁的时候调用。

  • 完成创建并返回。

可以看到上面的步骤非常的繁琐,每一个步骤都使用了大量代码来完成其功能,最复杂也是最难理解的当属循环依赖的处理,在真正进入doCreateBean前我们有必要了解下循环依赖。

二、创建bean的实例

当我们了解了循环依赖以后就可以深入分析创建bean的每个步骤了,首先我们从createBeanInstance开始。代码如下

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
   
   
    // Make sure bean class is actually resolved at this point.
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
   
   
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }
	// 如果工厂方法不为空则使用工厂方法初始化策略
    if (mbd.getFactoryMethodName() != null)  {
   
   
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
   
   
        synchronized (mbd.constructorArgumentLock) {
   
   
            // 一个类有多个构造方法,每个构造方法都有不同的参数,所以调用前需要先根据参数锁定目标构造方法
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
   
   
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    // 如果已经解析过则使用解析好的构造方法不需要再次锁定
    if (resolved) {
   
   
        if (autowireNecessary) {
   
   
            // 构造方法自动注入
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
   
   
            // 使用默认构造方法
            return instantiateBean(beanName, mbd);
        }
    }

    // 需要根据参数解析构造方法
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
   
   
        // 构造方法自动注入
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // No special handling: simply use no-arg constructor.
    return instantiateBean(beanName, mbd);
}

虽然代码中实例化的细节非常复杂,但是在CreateBean方法中我们还是可以清晰地看到实例化的逻辑的。

  • 如果在RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置了factory-method,那么Spring会尝试使用 **instantiateUsingFactoryMethod(beanName, mbd, args) **方法根据RootBeanDefinition中的配置生成bean的实例。
  • 解析构造方法并进行构造方法的实例化。因为一个bean对应的类中可能会有多个构造方法,而每个构造方法的参数不同,Spring在根据参数及类型去判断最终会使用哪个构造方法进行实例化。但是,判断的过程时比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从RootBeanDefinition中的属性 resolvedConstructorOrFactoryMethod 缓存的值去取,否则需要再次解析,并将解析的结果添加至RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod中。

1、autowireConstructor

对于实例的创建Spring分为了两种情况,一种是通用的实例化,另一种是带有参数的实例化。带有参数的实例化过程相当复杂,因为存在不确定性,所以在判断对应参数上做了大量工作。代码如下

public BeanWrapper autowireConstructor(
        final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
   
   

    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);

    Constructor<?> constructorToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;
	// explicitArgs通过getBean方法传入
    // 如果getBean方法调用的时候指定方法参数那么直接使用
    if (explicitArgs != null) {
   
   
        argsToUse = explicitArgs;
    }
    else {
   
   
        // 如果没有指定,则尝试从配置文件中读取
        Object[] argsToResolve = null;
        // 尝试从缓存中读取
        synchronized (mbd.constructorArgumentLock) {
   
   
            constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse != null && mbd.constructorArgumentsResolved) {
   
   
                // Found a cached constructor...
                argsToUse = mbd.resolvedConstructorArguments;
                if (argsToUse == null) {
   
   
                    // 配置的构造方法参数
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }
        // 如果缓存中存在
        if (argsToResolve != null) {
   
   
            // 解析参数类型,如给定方法的构造为为A(int, int),则通过此方法后就会把配置中的“1”,"1"转换为1,1
            // 缓存中的值可能是原始值也可能是最终值
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
        }
    }
	// 没有被缓存
    if (constructorToUse == null) {
   
   
        // Need to resolve the constructor.
        boolean autowiring = (chosenCtors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        ConstructorArgumentValues resolvedValues = null;

        int minNrOfArgs;
        if (explicitArgs != null) {
   
   
            minNrOfArgs = explicitArgs.length;
        }
        else {
   
   
            // 提取配置文件总的配置的构造方法参数
            ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
            // 用于承载解析后的构造方法参数的值
            resolvedValues = new ConstructorArgumentValues();
            // 能解析到的参数个数
            minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
        }

        // Take specified constructors, if any.
        Constructor<?>[] candidates = chosenCtors;
        if (candidates == null) {
   
   
            Class<?> beanClass = mbd.getBeanClass();
            try {
   
   
                candidates = (mbd.isNonPublicAccessAllowed() ?
                        beanClass.getDeclaredConstructors() : beanClass.getConstructors());
            }
            catch (Throwable ex) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值