spring源码阅读笔记08:bean加载之创建bean

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

spring源码阅读笔记08:bean加载之创建bean

木瓜芒果   2020-04-21 我要评论

  上文从整体视角分析了bean创建的流程,分析了Spring在bean创建之前所做的一些准备工作,并且简单分析了一下bean创建的过程,接下来就要详细分析bean创建的各个流程了,这是一个比较复杂的过程,也是Spring获取bean中最核心的一部分,主要包括如下部分,下面依次进行详细分析:

  • 构造bean;
  • 属性注入;
  • 初始化bean;
  • 注册DisposableBean;

1. 构造bean

  构造bean的逻辑在createBeanInstance()方法中:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    // 解析class
    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);
    }

    // 使用默认构造函数构造
    return instantiateBean(beanName, mbd);
}

  这里面的逻辑还是比较清晰的:

  1. 如果在RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置了factory-method,那么Spring会尝试使用instantiateUsingFactoryMethod()方法根据RootBeanDefinition中的配置生成bean的实例。

  2. 解析构造函数并进行构造函数的实例化。因为一个bean对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring会根据参数及类型去判断最终会使用哪个构造函数进行实例化。但是,判断的过程是一个比较消耗性能的步骤,所以采用了缓存机制,即如果已经解析过则不需要重复解析而是直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值去取,否则需要再次解析,并将解析的结果添加至RootBeanDefinition中的resolvedConstructorOrFactoryMethod中。

  下面再来看一下实例的创建,对于实例的创建Spring中分成了两种情况,一种是通用的实例化,另一种是带有参数的实例化。

1.1 带参数构造函数实例化

  带有参数的实例化过程相当复杂,因为存在着不确定性,所以在判断对应参数上做了大量工作,这个工作是委托给ConstructorResolver这个类: 

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 {
        // 如果在getBean方法时候没有指定则尝试从配置文件中解析
        Object[] argsToResolve = null;
        // 尝试从缓存中获取
        synchronized (mbd.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse != null && mbd.constructorArgumentsResolved) {
                // 从缓存获取
                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) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,"some exception message ^_^", ex);
            }
        }
        // 排序给定的构造函数,public构造函数优先参数数量降序、非public构造函数参数数量降序
        AutowireUtils.sortConstructors(candidates);
        int minTypeDiffWeight = Integer.MAX_VALUE;
        Set<Constructor<?>> ambiguousConstructors = null;
        List<Exception> causes = null;

        for (int i = 0; i < candidates.length; i++) {
            Constructor<?> candidate = candidates[i];
            Class<?>[] paramTypes = candidate.getParameterTypes();

            if (constructorToUse != null && argsToUse.length > paramTypes.length) {
                // 如果已经找到选用的构造函数并且需要的参数个数大于当前的构造函数参数个数则终止,因为已经按照参数个数降序排列
                break;
            }
            if (paramTypes.length < minNrOfArgs) {
                // 参数个数不相等
                continue;
            }

            ArgumentsHolder argsHolder;
            if (resolvedValues != null) {
                // 有参数则根据值构造对应参数类型的参数
                try {
                    String[] paramNames = null;
                    if (constructorPropertiesAnnotationAvailable) {
                        // 注解上获取参数名称
                        paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
                    }
                    if (paramNames == null) {
                        // 获取参数名称探索器
                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                        if (pnd != null) {
                            // 获取指定构造函数的参数名称
                            paramNames = pnd.getParameterNames(candidate);
                        }
                    }
                    // 根据名称和数据类型创建参数持有者
                    argsHolder = createArgumentArray(
                            beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
                }
                catch (UnsatisfiedDependencyException ex) {
                    if (this.beanFactory.logger.isTraceEnabled()) {
                        this.beanFactory.logger.trace(
                                "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
                    }
                    if (i == candidates.length - 1 && constructorToUse == null) {
                        if (causes != null) {
                            for (Exception cause : causes) {
                                this.beanFactory.onSuppressedException(cause);
                            }
                        }
                        throw ex;
                    }
                    else {
                        // Swallow and try next constructor.
                        if (causes == null) {
                            causes = new LinkedList<Exception>();
                        }
                        causes.add(ex);
                        continue;
                    }
                }
            }
            else {
                // Explicit arguments given -> arguments length must match exactly.
                if (paramTypes.length != explicitArgs.length) {
                    continue;
                }
                // 构造函数没有参数的情况
                argsHolder = new ArgumentsHolder(explicitArgs);
            }
            // 探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
            int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                    argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
            // 如果它代表着当前最接近的匹配则选择作为构造函数
            if (typeDiffWeight < minTypeDiffWeight) {
                constructorToUse = candidate;
                argsHolderToUse = argsHolder;
                argsToUse = argsHolder.arguments;
                minTypeDiffWeight = typeDiffWeight;
                ambiguousConstructors = null;
            }
            else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
                if (ambiguousConstructors == null) {
                    ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
                    ambiguousConstructors.add(constructorToUse);
                }
                ambiguousConstructors.add(candidate);
            }
        }

        if (constructorToUse == null) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,"some exception message ^_^");
        }
        else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,"some exception message ^_^" + ambiguousConstructors);
        }

        if (explicitArgs == null) {
            // 将解析的构造函数加入缓存
            argsHolderToUse.storeCache(mbd, constructorToUse);
        }
    }

    try {
        Object beanInstance;

        if (System.getSecurityManager() != null) {
            final Constructor<?> ctorToUse = constructorToUse;
            final Object[] argumentsToUse = argsToUse;
            beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    return beanFactory.getInstantiationStrategy().instantiate(
                            mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
                }
            }, beanFactory.getAccessControlContext());
        }
        else {
            beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
                    mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
        }
        // 将构建的实例加入BeanWrapper中
        bw.setWrappedInstance(beanInstance);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

  逻辑很复杂,代码量也很大,能够坚持读完都不容易。总结一下整个函数,主要在以下几个方面:

1. 构造函数参数的确定

  • 根据explicitArgs参数判断

  如果传入的参数explicitArgs不为空,那么可以直接确定参数,因为explicitArgs参数是在调用Bean的时候用户指定的,在BeanFactory类中存在这样的方法:

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

  在获取bean的时候,用户不但可以指定bean的名称还可以指定bean所对应类的构造函数或者工厂方法的方法参数,主要用于静态工厂方法的调用,而这里是需要给定完全匹配的参数的,所以,便可以判断,如果传入参数explicitArgs不为空,则可以确定构造函数参数就是它。

  • 从缓存中获取

  除此之外,确定参数的办法如果之前已经分析过,也就是说构造函数参数已经记录在缓存中,那么便可以直接拿来使用。而且,这里要提到的是,在缓存中缓存的可能是参数的最终类型也可能是参数的初始类型,例如:构造函数参数要求的是int类型,但是原始的参数值可能是String类型的"1",那么即使在缓存中得到了参数,也需要经过类型转换器的过滤以确保参数类型与对应的构造函数参数类型完全对应。

  • 从配置文件获取

  如果不能根据传入的参数explicitArgs确定构造函数参数,也无法在缓存中得到相关信息,那么就只能从头分析了。

  经过之前的分析,我们知道,Spring中配置文件的信息经过转换之后都会通过BeanDefinition实例承载,也就是参数mbd中包含的,那么可以通过调用mbd.getConstructorArgumentValues()来获取配置的构造函数信息。有了配置中的信息便可以获取对应的参数值信息了,获取参数值的信息包括直接指定值,如:直接指定构造函数中某个值为原始类型或String类型,或者是一个对其他bean的引用,这一处理是委托给resolveConstructorArguments()方法,它将返回能解析到的参数的个数。

2. 构造函数的确定

  经过了第一步后已经确定了构造函数的参数,接下来的任务就是根据构造函数参数在所有构造函数中锁定对应的构造函数,而匹配的方法就是根据参数个数匹配,所以在匹配之前需要先对构造函数按照public构造函数优先参数数量降序、非public构造函数参数数量降序。这样可以在遍历的情况下迅速判断排在后面的构造函数参数个数是否符合条件。

  由于在配置文件中并不是唯一限制使用参数位置索引的方式去创建,同样还支持指定参数名称进行设定参数值的情况,如<constructor-arg name="aa">,那么这种情况就需要首先确定构造函数中的参数名称。

  获取参数名称有两种方式,一种是通过注解的方式直接获取,另一种就是使用Spring中提供的工具类ParameterNameDiscoverer来获取。构造函数、参数名称、参数类型、参数值都确定后就可以锁定构造函数以及转换对应的参数类型了。

3. 根据确定的构造函数转换对应的参数类型

  主要是使用Spring中提供的类型转换器或者用户提供的自定义类型转换器进行转换。

4. 构造函数不确定性的验证

  当然,有时候即使构造函数、参数名称、参数类型、参数值都确定后也不一定会直接锁定构造函数,不同构造函数的参数为父子关系,所以Spring在最后又做了一次验证。

5. 根据实例化策略以及得到的构造函数及构造函数参数实例化Bean

1.2 不带参数的构造函数实例化

  相较于带有参数的构造函数的实例构造,不带参数的构造函数的实例化过程是很简单的,就是直接调用实例化策略进行实例化,这里就不贴代码了。

1.3 实例化策略

  现在构造函数以及确定好了,具备了实例化的条件,完全可以使用最简单的反射方法直接构造实例对象,但是Spring并没有这么做:

// SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
    // 如果有需要覆盖或者动态替换的方法则当然需要使用cglib进行动态代理,因为可以在创建代理的同时将动态方法织入类中
    // 但是如果没有需要动态改变的方法,为了方便直接反射就可以了
    if (beanDefinition.getMethodOverrides().isEmpty()) {
        Constructor<?> constructorToUse;
        synchronized (beanDefinition.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                final Class<?> clazz = beanDefinition.getBeanClass();
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    if (System.getSecurityManager() != null) {
                        constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {
                            public Constructor<?> run() throws Exception {
                                return clazz.getDeclaredConstructor((Class[]) null);
                            }
                        });
                    }
                    else {
                        constructorToUse =    clazz.getDeclaredConstructor((Class[]) null);
                    }
                    beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Exception ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
        // Must generate CGLIB subclass.
        return instantiateWithMethodInjection(beanDefinition, beanName, owner);
    }
}

// CglibSubclassingInstantiationStrategy.java
public Object instantiate(Constructor<?> ctor, Object[] args) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(this.beanDefinition.getBeanClass());
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setCallbackFilter(new CallbackFilterImpl());
    enhancer.setCallbacks(new Callback[] {
            NoOp.INSTANCE,
            new LookupOverrideMethodInterceptor(),
            new ReplaceOverrideMethodInterceptor()
    });

    return (ctor != null ? enhancer.create(ctor.getParameterTypes(), args) : enhancer.create());
}

  上面的程序中,首先判断如果beanDefinition.getMethodOverrides()为空也就是用户没有使用replace或者lookup的配置方法,那么直接使用反射的方式,简单快捷,但是如果使用了这两个特性,再直接使用反射的方式创建实例就不妥了,因为需要将这两个配置提供的功能切入进去,所以就必须要使用动态代理的方式将包含两个特性所对应的逻辑的拦截增强器设置进去,这样才可以保证在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例。

2. 属性注入

  当创建好了bean的实例之后,接着就需要将bean中的属性进行注入,这部分逻辑是在populateBean()方法中的,具体是如何实现的呢?

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    PropertyValues pvs = mbd.getPropertyValues();

    if (bw == null) {
        if (!pvs.isEmpty()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // 没有可填充的属性
            return;
        }
    }

    // 给InstantiationAwareBeanPostProcessors最后一次机会在属性设置前来改变bean
    // 比如:可以用来支持属性注入的类型
    boolean continueWithPropertyPopulation = true;

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 返回值为是否继续填充bean
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    // 如果后处理器发出停止填充命令则终止后续的执行
    if (!continueWithPropertyPopulation) {
        return;
    }

    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // 根据名称自动注入
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }

        // 根据类型自动注入
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }

        pvs = newPvs;
    }
    // 后处理器已经初始化
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    // 需要依赖检查
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 对所有需要依赖检查的属性进行后处理
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
            // 依赖检查,对于depends-on属性
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
    // 将属性应用到bean中
    applyPropertyValues(beanName, mbd, bw, pvs);
}

  在populateBean函数中提供了这样的处理流程

  1. InstantiationAwareBeanPostProcessor处理器的postProcessorAfterInstantiation函数的应用,此函数可以控制程序是否继续进行属性填充;
  2. 根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中;
  3. 应用InstantiationAwareBeanPostProcessor处理器的postProcessorPropertyValues()方法,在属性获取完毕并在填充前对属性进行再次处理,典型应用是RequiredAnnotationBeanPostProcessor类中对属性的验证;
  4. 将所有PropertyValues中的属性填充至BeanWrapper中;

  在上面的步骤中,我们着重分析一下依赖注入(autoworeByName/autowireByType)以及属性填充。

2.1 autowireByName

  首先来了解一下byName功能是如何实现的:

protected void autowireByName(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    // 寻找bw中需要依赖注入的属性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        if (containsBean(propertyName)) {
            // 递归初始化相关的bean
            Object bean = getBean(propertyName);
            pvs.add(propertyName, bean);
            // 注册依赖
            registerDependentBean(propertyName, beanName);
            if (logger.isDebugEnabled()) {
                logger.debug("Added autowiring by name from bean name '" + beanName +
                        "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                        "' by name: no matching bean found");
            }
        }
    }
}

  这里无非是在传入的参数pvs中找出已经加载的bean,并递归实例化,进而加入到pvs中。

2.2 autowireByType

  autowireByType与autowireByName在使用和理解层面上复杂程度相似,但是其实现的复杂程度却完全不一样。

protected void autowireByType(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }

    Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
    // 寻找bw中需要依赖注入的属性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        try {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // Don't try autowiring by type for type Object: never makes sense,
            // even if it technically is a unsatisfied, non-simple property.
            if (!Object.class.equals(pd.getPropertyType())) {
                // 探测指定属性的set方法
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                // 解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在autowiredBeanName中,当属性存在多个封装bean时,如:
                // @Autowired private List<A> aList;将会找到所有匹配A类型的bean并将其注入
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                for (String autowiredBeanName : autowiredBeanNames) {
                    // 注册依赖
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
                                propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                autowiredBeanNames.clear();
            }
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}

  实现根据名称自动匹配的第一步就是寻找bw中需要依赖注入的属性,同样对于根据类型自动匹配的实现来讲第一步也是寻找bw中需要依赖注入的属性,然后遍历这些属性并寻找类型匹配的bean,其中最复杂的就是寻找类型匹配的bean。Spring也提供了对集合的类型注入的支持,如使用注解的方式:

@Autowired
private List<Test> tests;

  Spring将会把所有与Test匹配的类型找出来并注入到tests属性中,正是由于这一因素,所以在autowireByType函数中,新建了局部变量autowiredBeanNames,用于存储所有依赖的bean,如果只是对非集合类的属性注入来说,此属性并无用处。

  对于寻找类型匹配的逻辑实现封装在了resolveDependency()函数中:

public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
        Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    if (descriptor.getDependencyType().equals(ObjectFactory.class)) {
        // ObjectFactory类注入的特殊处理
        return new DependencyObjectFactory(descriptor, beanName);
    }
    else if (descriptor.getDependencyType().equals(javaxInjectProviderClass)) {
        // javaxInjectProviderClass类注入的特殊处理
        return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);
    }
    else {
        // 通用处理逻辑
        return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter);
    }
}

protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName,
        Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
    // 用于支持Spring中新增的注解@Value
    Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
    if (value != null) {
        if (value instanceof String) {
            String strVal = resolveEmbeddedValue((String) value);
            BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
            value = evaluateBeanDefinitionString(strVal, bd);
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        return (descriptor.getField() != null ?
                converter.convertIfNecessary(value, type, descriptor.getField()) :
                converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
    }
    // 如果解析器没有成功解析,则需要考虑各种情况
    // 属性时数组类型
    if (type.isArray()) {
        Class<?> componentType = type.getComponentType();
        // 根据属性类型找到beanFactory中所有类型的匹配bean,
        // 返回值的构成为:key=匹配的beanName,value=beanName 对应的实例化后的bean(通过getBean(beanName)返回)
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);
        if (matchingBeans.isEmpty()) {
            // 如果autowire的require属性为true而找到的匹配项却为空则只能抛出异常
            if (descriptor.isRequired()) {
                raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
            }
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        // 通过转换器将bean的值转换为对应的type类型
        return converter.convertIfNecessary(matchingBeans.values(), type);
    }
    // 属性是Collection类型
    else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
        Class<?> elementType = descriptor.getCollectionType();
        if (elementType == null) {
            if (descriptor.isRequired()) {
                throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
            }
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);
        if (matchingBeans.isEmpty()) {
            if (descriptor.isRequired()) {
                raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
            }
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        return converter.convertIfNecessary(matchingBeans.values(), type);
    }
    // 属性是Map类型
    else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
        Class<?> keyType = descriptor.getMapKeyType();
        if (keyType == null || !String.class.isAssignableFrom(keyType)) {
            if (descriptor.isRequired()) {
                throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
                        "] must be assignable to [java.lang.String]");
            }
            return null;
        }
        Class<?> valueType = descriptor.getMapValueType();
        if (valueType == null) {
            if (descriptor.isRequired()) {
                throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
            }
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);
        if (matchingBeans.isEmpty()) {
            if (descriptor.isRequired()) {
                raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
            }
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        return matchingBeans;
    }
    else {
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            if (descriptor.isRequired()) {
                raiseNoSuchBeanDefinitionException(type, "", descriptor);
            }
            return null;
        }
        if (matchingBeans.size() > 1) {
            String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
            if (primaryBeanName == null) {
                throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
            }
            if (autowiredBeanNames != null) {
                autowiredBeanNames.add(primaryBeanName);
            }
            return matchingBeans.get(primaryBeanName);
        }
        // 已经可以确定只有一个匹配项
        Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(entry.getKey());
        }
        return entry.getValue();
    }
}

  这里首先尝试使用解析器进行解析,如果解析器没有成功解析,那么可能是使用默认的解析器没有做任何处理,或者是使用了自定义的解析器,但是对于集合等类型来说并不在解析范围之内,所以会再次对不同集合类型进行不同情况的处理,虽然对于不同集合类型处理方式不一致,但是大致思路是很相似的,所以这里只分析一下对数组类型的解析:

  • 首先获取数组封装的类型;
  • 根据属性类型找到beanFactory中所有类型的匹配bean;
  • 将找到的所有匹配的beanName加入到传入的autowiredBeanNames中;
  • 对找到的所有匹配的bean转换为对应的type类型并返回;

2.3 applyPropertyValues

  到这里,已经完成了对所有注入属性的获取,但是获取的属性是以PropertyValues形式存在的,还没有应用到已经实例化的bean中,这一工作是在applyPropertyValues中:

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    if (pvs == null || pvs.isEmpty()) {
        return;
    }

    MutablePropertyValues mpvs = null;
    List<PropertyValue> original;

    if (System.getSecurityManager() != null) {
        if (bw instanceof BeanWrapperImpl) {
            ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
        }
    }

    if (pvs instanceof MutablePropertyValues) {
        mpvs = (MutablePropertyValues) pvs;
        // 如果mpvs中的值已经被转换为对应的类型那么可以直接设置到beanwapper中
        if (mpvs.isConverted()) {
            // Shortcut: use the pre-converted values as-is.
            try {
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Error setting property values", ex);
            }
        }
        original = mpvs.getPropertyValueList();
    }
    else {
        // 如果pvs并不是使用MutablePropertyValues封装的类型,那么直接使用原始的属性获取方法
        original = Arrays.asList(pvs.getPropertyValues());
    }

    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    // 获取对应的解析器
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

    // Create a deep copy, resolving any references for values.
    List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
    boolean resolveNecessary = false;
    // 遍历属性,将属性转换为对应类的对应属性的类型
    for (PropertyValue pv : original) {
        if (pv.isConverted()) {
            deepCopy.add(pv);
        }
        else {
            String propertyName = pv.getName();
            Object originalValue = pv.getValue();
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
            Object convertedValue = resolvedValue;
            boolean convertible = bw.isWritableProperty(propertyName) &&
                    !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
            if (convertible) {
                convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
            }
            // Possibly store converted value in merged bean definition,
            // in order to avoid re-conversion for every created bean instance.
            if (resolvedValue == originalValue) {
                if (convertible) {
                    pv.setConvertedValue(convertedValue);
                }
                deepCopy.add(pv);
            }
            else if (convertible && originalValue instanceof TypedStringValue &&
                    !((TypedStringValue) originalValue).isDynamic() &&
                    !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                pv.setConvertedValue(convertedValue);
                deepCopy.add(pv);
            }
            else {
                resolveNecessary = true;
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }
    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }

    // Set our (possibly massaged) deep copy.
    try {
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}

3. 初始bean

  在bean配置时bean中有一个init-method的属性,这个属性的作用是在bean初始化时调用init-method属性指定的方法来根据用户业务执行相应的初始化工作,初始化的工作是在bean完成实例化并且进行了属性填充之后进行的。实现这个功能的代码在initializeBean()方法中:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
        // 对特殊的bean的处理:Aware、BeanClassLoaderAware、BeanFactoryAware
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 应用后处理器
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 激活用户自定义的init方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        // 应用后处理器
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

  这里除了调用用户指定的方法执行初始化,还做了其它一些操作,主要有激活Aware方法、应用后处理器、激活自定义的init方法。

3.1 激活Aware方法

  我们先了解一下Aware的使用,Spring中提供了一些Aware相关接口,比如BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等,实现这些Aware接口的bean在被初始化之后,可以取得一些相对应的资源,例如实现了BeanFactoryAware接口的bean在初始化后,Spring容器将会注入BeanFactory的实例,而实现了ApplicationContextAware接口的bean,在bean被初始化后,将会被注入ApplicationContext的实例等。这里先通过示例方法来了解一下Aware的使用:

// 定义普通bean
public class Hello {
    public void say(){
        System.out.println("hello");
    }
}

// 定义BeanFactoryAware类型的bean
public class Test implements BeanFactoryAware {
    private BeanFactory beanFactory;

    // 声明bean的时候Spring会自动注入BeanFactory
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    public void testAware() { 
        // 通过hello这个bean id从beanFactory获取实例
        Hello hello = (Hello)beanFactory.getBean("hello");
        hello.say();
    }
}

// 使用main方法测试
public static void main(String[] args){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    Test test = (Test)ctx.getBean("test");
    test.testAware();
}

  运行测试类,控制台会输出:hello

  按照上面的方法我们可以获取到Spring中BeanFactory,并且可以根据BeanFactory获取所有bean,以及进行相关设置。当然还有其他Aware的使用方法都大同小异,这里就不一一列举了。我们接下来看一下Spring是如何激活Aware方法的。

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

  这个就是直接判断是否实现接口,然后调用对应的set方法。

3.2 处理器的应用

  BeanPostProcessor相信用过Spring的同学都听过,这是Spring中开放式架构中一个必不可少的亮点,给用户充足的权限去更改或者扩展Spring,而除了BeanPostProcessor外还有很多其他的PostProcessor,都是继承自BeanPostProcessor,给用户提供接口进行扩展,这又是如何实现的呢?其实就是在调用用户自定义的init方法之前和之后分别调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法,用户可以在这两个方法中定义自己的业务逻辑。

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        result = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        result = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

3.3 激活自定义的init方法

  由用户定制的初始化方法除了我们熟知的使用配置init-method外,还有让自定义的bean实现InitializingBean接口,并在afterPropertiesSet中实现自己的初始化业务逻辑。

  init-method与afterPropertiesSet都是在初始化bean时执行,执行顺序是afterPropertiesSet先执行,而init-method后执行。

  在invokeInitMethod()方法中就实现了这两个步骤的初始化方法调用:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
        throws Throwable {
    // 首先会检查是否是InitializingBean,如果是的话需要调用afterPropertiesSet方法
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                    public Object run() throws Exception {
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            // 属性初始化后的处理
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null) {
        String initMethodName = mbd.getInitMethodName();
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 调用自定义初始化方法
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

4. 注册DisposableBean

  Spring中不但提供了对于初始化方法的扩展入口,同样也提供了销毁方法的扩展入口,对于销毁方法的扩展,除了我们熟知的配置属性destroy-method方法外,用户还可以注册后处理器DestructionAwareBeanPostProcessor来统一处理bean的销毁方法,代码如下: 

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
        if (mbd.isSingleton()) {
            // 单例模式下注册需要销毁的bean,此方法中会处理实现DisposableBean的bean,
            // 并且所有的bean使用DestructionAwareBeanPostProcessors处理
            // DisposableBean DestructionAwareBeanPostProcessors
            registerDisposableBean(beanName,
                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
        }
        else {
            // 自定义scope的处理
            Scope scope = this.scopes.get(mbd.getScope());
            if (scope == null) {
                throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");
            }
            scope.registerDestructionCallback(beanName,
                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
        }
    }
}

5. 总结

  本文篇幅稍长,详细分析了创建bean的各个步骤,包括构造bean、属性注入、初始化bean、注册DisposableBean,其中构造bean和属性注入的逻辑比较复杂,初始化和注册DisposableBean相对简单。

构造bean大致流程如下(带参数构造函数):

  • 构造函数参数的确定
  • 构造函数的确定
  • 构造函数的确定
  • 根据实例化策略以及得到的构造函数及构造函数参数实例化Bean

属性注入大致流程如下:

  • 寻找需要依赖注入的属性
  • 根据名称/类型寻找匹配的属性bean
  • 注入属性

  历经艰难,至此bean的加载就完成了,到这里应该也能够感受到一个简单IOC思想在Spring那里实现起来有多复杂了!能看到这里的同学都不容易,为自己点个赞吧!

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们