Spring源码分析(八)依赖注入源码解析1:autowire自动注入 和 @Autowired注入

2023-11-20

Spring中到底有几种依赖注入的方式?

首先分两种:

  1. 手动注入
  2. 自动注入

手动注入

在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定了值

<bean name="userService" class="com.luban.service.UserService">
	<property name="orderService" ref="orderService"/>
</bean>

上面这种底层是通过set方法进行注入。

<bean name="userService" class="com.luban.service.UserService">
	<constructor-arg index="0" ref="orderService"/>
</bean>

上面这种底层是通过构造方法进行注入。

所以手动注入的底层也就是分为两种:

  1. set方法注入
  2. 构造方法注入

自动注入

自动注入也分为两种:

  1. XML的autowire自动注入
  2. @Autowired注解的自动注入

接下来开始源码分析

入口 - 属性填充阶段

直接看Bean生命周期的属性填充阶段:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {...}

    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    // 实例化之后,属性填充之前
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {...}

    //属性值,用来通过set方法注入的值
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    //1. autowire自动注入
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            //autowire根据Name自动注入(其实只是收集注入值到newPvs中)
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            //autowire根据Type自动注入(其实只是收集注入值到newPvs中)
            autowireByType(beanName, mbd, bw, newPvs);
        }
        //核心,ByName或者ByType找到属性对应的值以后,就会放到pvs中
        pvs = newPvs;
    }

    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
	
    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        //2.@Autowired注解注入
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            //默认提供的实现里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法直接给对象中的属性赋值
            //	AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
            //	AutowiredAnnotationBeanPostProcessor会处理@Autowired、@Value、 @Inject 注解
            //	CommonAnnotationBeanPostProcessor会处理@Resource注解
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    //获取筛选后的propertydescriptor,属性描述器集合(排除被忽略的依赖项类型 或 在被忽略的依赖项接口上 定义的属性)
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                //过时了,在工厂将给定的属性值应用到给定的bean之前,对它们进行后处理。
                //允许检查是否满足了所有依赖项,例如基于bean属性设置器上的“Required”注解。
                //	默认实现RequiredAnnotationBeanPostProcessor中,支持给"setXXX"方法加上@Required注解
                //	标记为“必需的”,简单来说,就是要求pvs属性值中一定要存在 给@Required标记的set方法注入的值  
                pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }

    //依赖项检查,确保所有公开的属性都已设置
    //依赖项检查可以是对象引用、“简单”属性(原语和String)或所有(两者都是)
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    if (pvs != null) {
        //3.属性赋值(把pvs里的属性值给bean进行赋值!!!!!)
        //autowire自动注入,其实只是收集注入的值,放到pvs中,最终赋值的动作还是在这里!!
        //PropertyValues中的值优先级最高
        //	如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired的
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

1. autowire自动注入

xml中可以通过autowire属性设置:

<bean id="user" class="com.yth.service.User" autowire="byName"/>

@Bean方式也行

@ComponentScan("com.yth")
public class AppConfig {
    @Bean(autowire = Autowire.BY_TYPE)
    public OrderService orderService() {
        return new OrderService();
    }
}

ByName

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByName

protected void autowireByName(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
	//1.1 获取当前bean中能进行自动注入的属性名
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    //遍历每个属性名,并去获取Bean对象,并设置到pvs中
    for (String propertyName : propertyNames) {
        if (containsBean(propertyName)) {
        	//直接根据beanName获取Bean
            Object bean = getBean(propertyName);
            //这里把propertyName对应的属性值保存到了MutablePropertyValues
            //暂时只是记录了一下,还没有赋值
            pvs.add(propertyName, bean);
            //记录一下propertyName对应的Bean被beanName给依赖了
            //(之前讲DependsOn注解也走过这个方法)
            registerDependentBean(propertyName, beanName);
            if (logger.isTraceEnabled()) {...}
        }
        else {...}
    }
}
  • 直接根据beanName获取Bean
  • 只做了记录,还没有进行赋值的动作!!

ByType

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByType

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

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

    Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    //1.1 获取当前bean中能进行自动注入的属性名
    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 an unsatisfied, non-simple property.
            // 如果需要注入的属性类型是Object类型没有意义(注入的时候发现类型是Object这咋注入)
            if (Object.class != pd.getPropertyType()) {
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                // 在优先级后处理器的情况下,不允许为了类型匹配而立即初始化。
                //	为什么不允许,因为我自己是PriorityOrdered,是优先级最高的,不能有比我创建得更早的
                //	PriorityOrdered:Ordered接口的扩展,表示优先级排序:priorityorordered对象总是应用在普通Ordered对象之前,而不管其顺序值如何。
                // 	eager表示立即初始化,表示在根据类型查找Bean时,允不允许进行Bean的创建,如果当前Bean实现了PriorityOrdered则不允许
                boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);

                //依赖注入描述器
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                
                // 1.2 根据类型找到结果(@Autowired注解也是用的这个方法,非常重要和复杂)
                // 这个方法下一节再讲,很复杂!!
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                if (autowiredArgument != null) {
                    //和ByName同理,只是记录
                    pvs.add(propertyName, autowiredArgument);
                }
                //因为有可能注入的时候是个List<XXXX>,所以这里autowiredBeanNames是个集合
                for (String autowiredBeanName : autowiredBeanNames) {
                    //记录一下autowiredBeanName对应的Bean被beanName给依赖了
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isTraceEnabled()) {...}
                }
                autowiredBeanNames.clear();
            }
        }
        catch (BeansException ex) {...}
    }
}

同理,只做了记录,还没有进行赋值的动作!!

1.1 获取当前bean中能进行自动注入的属性名

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#unsatisfiedNonSimpleProperties

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
    Set<String> result = new TreeSet<>();
    PropertyValues pvs = mbd.getPropertyValues();
    //获取当前对象中,所有符合javaBean定义的有get/set方法的属性的属性描述器
    //	底层其实只会判断get/set方法,有get/set方法就会解析成一个属性描述器,但是要求get/set方法满足一定的条件
    //  条件简单理解总结就是:
    //		get方法的定义是: 方法参数个数为0个,并且方法名字以"get"开头 
	//						或者 方法名字以"is"开头并 且方法的返回类型为boolean
	//		set方法的定义是:方法参数个数为1个,方法名字以"set"开头,且方法返回类型为 void
    PropertyDescriptor[] pds = bw.getPropertyDescriptors();

    //什么样的属性能进行自动注入?
    //1.该属性有对应的set方法	pd.getWriteMethod() != null
    //2.该属性类型没有在ignoredDependencyTypes中
    //3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中 
    //4.getPropertyValues中不能包含该属性 !pvs.contains(pd.getName())
    //5.属性类型不是简单类型,比如int、Integer、int[]
    for (PropertyDescriptor pd : pds) {
        if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
                !BeanUtils.isSimpleProperty(pd.getPropertyType())) {
            result.add(pd.getName());
        }
    }
    return StringUtils.toStringArray(result);
}

什么样的属性能进行自动注入?

  1. 该属性有对应的set方法 pd.getWriteMethod() != null
  2. 该属性类型没有在ignoredDependencyTypes中
  3. 如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
  4. getPropertyValues中不能包含该属性 !pvs.contains(pd.getName())
  5. 属性类型不是简单类型,比如int、Integer、int[]

[2,3]:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#isExcludedFromDependencyCheck

protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
    //AutowireUtils.isExcludedFromDependencyCheck:排除了CGLIB定义的属性
    //ignoredDependencyTypes:依赖项检查和自动装配时要忽略的依赖项类型,是一个类对象集合:例如,字符串。默认是没有的。
    //ignoredDependencyInterfaces:依赖项检查和自动装配时要忽略的依赖项接口,是一个类对象的集合。默认情况下,只有BeanFactory接口被忽略。
    return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
            this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
            AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}

[4]:比如我们可以在Bean生命周期的 BeanDefinition后置处理阶段,给PropertyValues赋值,这样相同的属性名称,在当前流程中就会跳过该属性,肯定程序员自定义的优先级高喽。
在这里插入图片描述

[5]:判断是否是简单类型
org.springframework.beans.BeanUtils#isSimpleProperty

public static boolean isSimpleProperty(Class<?> type) {
    Assert.notNull(type, "'type' must not be null");
    return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
}

public static boolean isSimpleValueType(Class<?> type) {
    //isPrimitiveOrWrapper方法中,void/Void也会返回true,所以这里一开始就单独判断了一下。
    return (Void.class != type && void.class != type &&
            //以下这些都属于简单类型
            //isPrimitiveOrWrapper:检查给定的类是否代表
        	//		一个原语(即boolean、byte、char、short、int、long、float或double)、void
        	//		或这些类型的包装器(即Boolean、Byte, Character, Short, Integer, Long, Float, Double, or Void)。
            (ClassUtils.isPrimitiveOrWrapper(type) ||
            Enum.class.isAssignableFrom(type) ||
            CharSequence.class.isAssignableFrom(type) ||
            Number.class.isAssignableFrom(type) ||
            Date.class.isAssignableFrom(type) ||
            Temporal.class.isAssignableFrom(type) ||
            URI.class == type ||
            URL.class == type ||
            Locale.class == type ||
            Class.class == type));
}

注意:

  • isPrimitiveOrWrapper方法中,void/Void也会返回true,所以在isSimpleValueType中一开始会单独判断。
  • Enum、CharSequence、Number…这些都认为是简单类型
  • autowire自动注入会忽略简单数据类型,但是@Autowire不会忽略。

PropertyDescriptor

属性描述器,java.beans提供的。 (java.beans.PropertyDescriptor)
java规范中,认为Bean的属性要有get和set方法
在这里插入图片描述

我们找下PropertyDescriptor是怎么生成的:

org.springframework.beans.BeanWrapper#getPropertyDescriptors    //接口
org.springframework.beans.BeanWrapperImpl#getPropertyDescriptors
org.springframework.beans.BeanWrapperImpl#getCachedIntrospectionResults
org.springframework.beans.CachedIntrospectionResults#forClass
org.springframework.beans.CachedIntrospectionResults#CachedIntrospectionResults	//构造方法
org.springframework.beans.CachedIntrospectionResults#getBeanInfo(java.lang.Class<?>)
org.springframework.beans.BeanInfoFactory#getBeanInfo	//接口
org.springframework.beans.ExtendedBeanInfoFactory#getBeanInfo
java.beans.Introspector#getBeanInfo(java.lang.Class<?>) //从这里开始就是jdk提供的方法了
java.beans.Introspector#getBeanInfo()
java.beans.Introspector#getTargetPropertyInfo

在这里插入图片描述

java.beans.Introspector#getTargetPropertyInfo

private PropertyDescriptor[] getTargetPropertyInfo() {

    // Check if the bean has its own BeanInfo that will provide
    // explicit information.
    // 检查bean是否有自己的BeanInfo来提供显式信息。 (支持自定义BeanInfo)
    PropertyDescriptor[] explicitProperties = null;
    if (explicitBeanInfo != null) {...}

    //检查父类有没有自定义的BeanInfo来提供显式信息
    if (explicitProperties == null && superBeanInfo != null) {...}
	
    //检查额外的类信息(也是通过explicitBeanInfo,自定义BeanInfo提供的)
    for (int i = 0; i < additionalBeanInfo.length; i++) {...}
    
	//explicitProperties是自定义的,如果没有自定义指定,会利用反射解析获取属性信息
    if (explicitProperties != null) {
        // Add the explicit BeanInfo data to our results.
        addPropertyDescriptors(explicitProperties);
    } else {
        // 如果没有自定义指定,会利用反射解析获取属性信息
    	
        // Apply some reflection to the current class.
		// 否则对当前类应用反射进行解析
        // First get an array of all the public methods at this level
        // 获取所有public方法
        Method methodList[] = getPublicDeclaredMethods(beanClass);

        // Now analyze each method.
        for (int i = 0; i < methodList.length; i++) {
            Method method = methodList[i];
            if (method == null) {
                continue;
            }
            // skip static methods.
            // 跳过静态方法
            int mods = method.getModifiers();
            if (Modifier.isStatic(mods)) {
                continue;
            }
            //方法名
            String name = method.getName();
            //方法入参
            Class<?>[] argTypes = method.getParameterTypes();
            //方法返回值
            Class<?> resultType = method.getReturnType();
            int argCount = argTypes.length;
            PropertyDescriptor pd = null;
        	//方法名长度小于3且不是is开头,肯定不属于规范的get/set方法
            if (name.length() <= 3 && !name.startsWith(IS_PREFIX)) {
                // Optimization. Don't bother with invalid propertyNames.
                continue;
            }

            try {
            	//方法入参个数0的情况
                if (argCount == 0) {
                    if (name.startsWith(GET_PREFIX)) {
                        // Simple getter
                        pd = new PropertyDescriptor(this.beanClass, name.substring(3), method, null);
                    } else if (resultType == boolean.class && name.startsWith(IS_PREFIX)) {
                        // Boolean getter
                        pd = new PropertyDescriptor(this.beanClass, name.substring(2), method, null);
                    }
                } 
                //方法入参个数1的情况
                else if (argCount == 1) {
                    if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
                        pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
                    } else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
                        // Simple setter
                        pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
                        if (throwsException(method, PropertyVetoException.class)) {
                            pd.setConstrained(true);
                        }
                    }
                }
                //方法入参个数2的情况
                else if (argCount == 2) {
                        if (void.class.equals(resultType) && int.class.equals(argTypes[0]) && name.startsWith(SET_PREFIX)) {
                        pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, null, method);
                        if (throwsException(method, PropertyVetoException.class)) {
                            pd.setConstrained(true);
                        }
                    }
                }
            } catch (IntrospectionException ex) {...}

            if (pd != null) {
                // If this class or one of its base classes is a PropertyChange
                // source, then we assume that any properties we discover are "bound".
                if (propertyChangeSource) {...}
                addPropertyDescriptor(pd);
            }
        }
    }
    //通过合并属性描述符列表来填充属性描述符表。(属性分类合并)
    //	按照java规范来说,一个属性至少有get/set两个方法,对于一个属性描述器
    processPropertyDescriptors();

    // Allocate and populate the result array.
    PropertyDescriptor result[] =
            properties.values().toArray(new PropertyDescriptor[properties.size()]);

    // Set the default index.
    if (defaultPropertyName != null) {...}

    return result;
}

判断方法入参个数:

  • 0个的情况:
    • 方法名以"get"开头认为是get方法
    • 方法名以"is"开头,且返回值为boolean类型认为是get方法
  • 1个的情况:
    • 入参类型为int,且方法名以"get"开头认为是get方法(IndexedPropertyDescriptor)
    • 返回值类型为void,且方法名以"set"开头认为是set方法
  • 2个的情况:
    • 返回值类型为void,第一个入参类型为int,且方法名以"set"开头认为是set方法(IndexedPropertyDescriptor)

IndexedPropertyDescriptor:

  • 描述了一个类似数组的属性,它具有索引读和/或索引写方法来访问数组的特定元素。
  • 索引属性还可以提供简单的非索引读和写方法。如果存在,则读写. 索引read方法返回的类型 的数组。

简单概括就是:

  • get方法的定义是: 方法参数个数为0个,并且方法名字以"get"开头

    或者 方法名字以"is"开头并 且方法的返回类型为boolean

  • set方法的定义是:方法参数个数为1个,方法名字以"set"开头,且方法返回类型为 void

所以getClass方法也被解析成了一个属性PropertyDescriptor
在这里插入图片描述

1.2 根据类型找结果

@Autowired注解也是用的这个方法,非常重要和复杂
这个方法下一节再讲,很复杂!!

2. @Autowired注解注入

注解注入的实现是依赖BeanPostProcessor的扩展机制实现的,即InstantiationAwareBeanPostProcessor

if (hasInstAwareBpps) {
    if (pvs == null) {
        pvs = mbd.getPropertyValues();
    }
    //2.@Autowired注解注入
    for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
        //默认提供的实现里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法直接给对象中的属性赋值
        //	AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
        //	AutowiredAnnotationBeanPostProcessor会处理@Autowired、@Value、 @Inject 注解
        //	CommonAnnotationBeanPostProcessor会处理@Resource注解
        PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
        if (pvsToUse == null) {...}
        pvs = pvsToUse;
    }
}

InstantiationAwareBeanPostProcessor的实现中:

  • AutowiredAnnotationBeanPostProcessor会处理@Autowired、@Value、 @Inject 注解
  • CommonAnnotationBeanPostProcessor会处理@Resource注解

我们先分析AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor相对简单,逻辑也和@Autowired的差不多。

AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessors实现了两个接口:
在这里插入图片描述

其中SmartInstantiationAwareBeanPostProcessor继承于InstantiationAwareBeanPostProcessor,比它更强大:
在这里插入图片描述


以后讲,先不管。

看到它实现了两个接口:InstantiationAwareBeanPostProcessor(SmartInstantiationAwareBeanPostProcessor),MergedBeanDefinitionPostProcessor

按照Bean的生命周期流程的执行顺序:

  • 我们先看MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition方法的实现
  • 再看InstantiationAwareBeanPostProcessor.postProcessProperties方法的实现

在这里插入图片描述

postProcessMergedBeanDefinition:解析注入点并缓存
postProcessProperties:基于注入点属性注入

2.1 解析注入点并缓存

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    // 首先快速检查并发map,尽量减少锁的范围。
    
    // InjectionMetadata:封装了当前类中所有的注入点
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        //同步锁+双重检查
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                //解析注入点并缓存(被@Autowired标记的属性、方法..)
                metadata = buildAutowiringMetadata(clazz);
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}

解析注入点:

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    //a. 判断当前类是否需要查找注入点(包路径是java.开头的类不需要找注入点)
    //比如如果一个Bean的类型是String...那么则根本不需要进行依赖注入
    if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
        //不是候选类,直接返回
        return InjectionMetadata.EMPTY;
    }

    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    	//遍历targetClass中所有的field
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            //b. field上是否存在@Autowired、@Value、@Inject其中的一个
            MergedAnnotation<?> ann = findAutowiredAnnotation(field);
            if (ann != null) {
                //static field不是注入点,不会进行自动注入
                //e.因为静态属性是属于类的,而不是属于对象的。
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {...}
                    return;
                }
                //c.判断是否要必须注入,针对@Autowired的required属性。
                boolean required = determineRequiredStatus(ann);
                //构造字段注入点
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });

        //遍历targetClass中所有的Method
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            //d.找到所提供的桥接方法的原始方法
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            //比较桥接方法和它桥接的方法的特征。如果参数和返回类型相同,则它是Java 6中引入的“可见性”桥接方法
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                //“可见性”桥接方法也会过滤
                return;
            }
            //b. 判断method上是否存在@Autowired、@Value、@Inject其中的一个
            MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
            if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                //e.static method不是注入点,不会进行自动注入
                if (Modifier.isStatic(method.getModifiers())) {
                    if (logger.isInfoEnabled()) {...}
                    return;
                }
                //set方法最好有入参,做个日志提示(没有参数、1个参数、多个参数都可以)
                //就算@Autowired标记的方法没有入参,Spring也会去执行,只是不会去找参数类型对应的实例
                if (method.getParameterCount() == 0) {...}
                //c.判断是否要必须注入,针对@Autowired的required属性。
                boolean required = determineRequiredStatus(ann);
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                //构造方法注入点
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });

        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    //do while循环,递归处理父类
    while (targetClass != null && targetClass != Object.class);

    //将所有注入点整体封装成一个对象返回
    return InjectionMetadata.forElements(elements, clazz);
}

a. 判断当前类是否需要查找注入点

org.springframework.core.annotation.AnnotationUtils#isCandidateClass(java.lang.Class<?>, java.util.Collection<java.lang.Class<? extends java.lang.annotation.Annotation>>)

autowiredAnnotationTypes的值:
在这里插入图片描述

public static boolean isCandidateClass(Class<?> clazz, Collection<Class<? extends Annotation>> annotationTypes) {
    //annotationTypes此时就是@Autowired、@Value、@Inject
    for (Class<? extends Annotation> annotationType : annotationTypes) {
        if (isCandidateClass(clazz, annotationType)) {
            return true;
        }
    }
    return false;
}

public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType) {
    return isCandidateClass(clazz, annotationType.getName());
}

public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
    //注解名字是java.开头的,代表需要查找注入点
    if (annotationName.startsWith("java.")) {
        return true;
    }
    //什么情况下不需要找注入点呢?主要看这:
    if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
        return false;
    }
    //默认true,大部分情况下类都是要找注入点的
    return true;
}

org.springframework.core.annotation.AnnotationsScanner#hasPlainJavaAnnotationsOnly(java.lang.Class<?>)

static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
    //java.开头的类不需要找注入点
    return (type.getName().startsWith("java.") || type == Ordered.class);
}

b. 判断field/method上是否存在@Autowired、@Value、@Inject其中的一个

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation

private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    //获取指定元素上的所有注解和元注解。(默认不包括任何继承的注解)
    MergedAnnotations annotations = MergedAnnotations.from(ao);
    for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
        MergedAnnotation<?> annotation = annotations.get(type);
        if (annotation.isPresent()) {
            return annotation;
        }
    }
    return null;
}

其中autowiredAnnotationTypes值在构造函数里初始化了:@Autowired、@Value、@Inject
在这里插入图片描述

c. 判断是否要必须注入,针对@Autowired的required属性

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineRequiredStatus(org.springframework.core.annotation.MergedAnnotation<?>)

protected boolean determineRequiredStatus(MergedAnnotation<?> ann) {
    //调用MergedAnnotation.asMap方法,传入lambda表达式的一个对象,生成AnnotationAttributes对象
    return determineRequiredStatus(ann.<AnnotationAttributes> asMap(
        mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
}

protected boolean determineRequiredStatus(AnnotationAttributes ann) {
    //requiredParameterName="required"
    //requiredParameterValue=true
    //判断注解上是否包含required属性,并且是否为true
    return (!ann.containsKey(this.requiredParameterName) ||
            this.requiredParameterValue == ann.getBoolean(this.requiredParameterName));
}

在这里插入图片描述

d. 找到所提供的桥接方法的原始方法

什么情况下会有桥接方法?

public interface UserInterface<T> {
    void setOrderService(T t);
}
@Component
public class UserService implements UserInterface<OrderService> {

    private OrderService orderService;

    @Override
    @Autowired
    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }

    public void test() {
        System.out.println("test123");
    }

}

此时这段代码应该只有一个注入点,但是我们看下UserService对应的字节码:
在这里插入图片描述

可以看到在UserSerivce的字节码中有两个setOrderService方法:

  1. public setOrderService(Lcom/zhouyu/service/OrderService;)V
  2. public synthetic bridge setOrderService(Ljava/lang/Object;)V

并且都是存在@Autowired注解的。

java字节码层面针对泛型方法,就会特殊处理生成一个synthetic bridge的方法
java泛型,翻译成字节码,底层其实就是一个Object类型。(泛型、桥接方法、泛型擦除)

简单通过反射就会拿到两个方法,所以在Spring中需要处理这种情况,当遍历到桥接方法时,得找到原方法。

e. static的字段或方法为什么不支持

Demo演示:

@Component
@Scope("prototype")
public class OrderService {

}
@Component
@Scope("prototype")
public class UserService  {

	@Autowired
	private static OrderService orderService;

	public void test() {
		System.out.println("test123");
	}

}

看上面代码,UserService和OrderService都是原型Bean,假设Spring支持static字段进行自动注入,那么现在调用两次

  1. UserService userService1 = context.getBean(“userService”)
  2. UserService userService2 = context.getBean(“userService”)

问此时,userService1的orderService值是什么?还是它自己注入的值吗?
答案是不是,一旦userService2 创建好了之后,static orderService字段的值就发生了修改了,从而出现bug。

2.2 基于注入点属性注入

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //找注入点(所有被@Autowired注解了的Field或Method)
    //findAutowiringMetadata方法在上一步,BeanDefinition的后置流程中已经执行过了,所以此时直接从缓存拿了
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        //注入
        metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {...}
    catch (Throwable ex) {...}
    return pvs;
}

org.springframework.beans.factory.annotation.InjectionMetadata#inject

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements;
    Collection<InjectedElement> elementsToIterate =
            (checkedElements != null ? checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        //遍历每个注入点,进行依赖注入
        for (InjectedElement element : elementsToIterate) {
            element.inject(target, beanName, pvs);
        }
    }
}

方法和字段注入点对应的类型:
在这里插入图片描述

a. 字段注入

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject

    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Field field = (Field) this.member;
        Object value;
        //缓存,一开始肯定没有缓存
        if (this.cached) {...}
        else {
            //根据field从BeanFactory中查到匹配的Bean对象
            value = resolveFieldValue(field, bean, beanName);
        }
        //反射给field赋值
        if (value != null) {
            ReflectionUtils.makeAccessible(field);
            field.set(bean, value);
        }
    }

resolveFieldValue:关于怎么找的,比较复杂,下一节再说。

b.方法注入

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    //如果pvs中已经有当前注入点的值了,则跳过注入(autowire注入、set方法注入的优先级更高)
    if (checkPropertySkipping(pvs)) {
        return;
    }
    Method method = (Method) this.member;
    Object[] arguments;
    //缓存,一开始肯定没有缓存
    if (this.cached) {...}
    else {
        //根据方法信息找值,@Autowired注解标记的方法允许多个参数
        //怎么找下一节再说。
        arguments = resolveMethodArguments(method, bean, beanName);
    }
    if (arguments != null) {
        try {
            //反射调方法
            ReflectionUtils.makeAccessible(method);
            method.invoke(bean, arguments);
        }
        catch (InvocationTargetException ex) {...}
    }
}

3. PropertyValues手动注入

把pvs(PropertyValues属性)里的属性值给bean进行赋值!

  • 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
  • 通过pvs里的属性值给bean进行赋值,需要提供写方法才生效

PropertyValues怎么设置?

  • pvs里的属性值可以利用autowire自动注入的方式收集
  • 也可以手动设置(优先级最高),比如可以通过以下方式设置让属性赋值生效:
    在这里插入图片描述

applyPropertyValues 方法的主要逻辑是遍历 bd.propertyValues 中的 PropertyValue 属性,根据引用类型提取出对象实例,再将这个对象实例转换成可以直接注入的实例。

  1. 解析对象:valueResolver.resolveValueIfNecessary(pv, originalValue) 将 pv.value 解析成实例对象。
  2. 类型转换:convertForProperty(resolvedValue, propertyName, bw, converter) 将 resolvedValue 转换成可直接进行类型注入的类型。
  3. 依赖注入: bw.setPropertyValues(mpvs) 将解析后的属性注入到 bw 实例中
  4. 结果缓存:Spring 会将 valueResolver 和 converter 解析后的最终对象缓存到 pv 中,提高效率。如果全部 pv 都不需要重新解析,则设置 mpvs.converted=true。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues

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

    if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {...}

    MutablePropertyValues mpvs = null;
    List<PropertyValue> original;
	//1.获取List<PropertyValue>,如果已经解析过,则直接注入后返回
    
    //通常来说,默认实现就是MutablePropertyValues
    if (pvs instanceof MutablePropertyValues) {
        mpvs = (MutablePropertyValues) pvs;
        //isConverted:返回该holder是否只包含转换后的值(true),或者值是否仍然需要转换(false)。
        //MutablePropertyValues已经解析,直接注入,在方法解析后会缓存已经解析的PropertyValue
        if (mpvs.isConverted()) {
            // Shortcut: use the pre-converted values as-is.
            try {
                // BeanWrapper属性注入
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {...}
        }
        original = mpvs.getPropertyValueList();
    }
    else {
        original = Arrays.asList(pvs.getPropertyValues());
    }

    //类型转换器
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    //BeanDefinitionValueResolver:解析器,用于解析PropertyValue,如间接引用替换成直接对象
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);


    //2.逐个解析、转换PropertyValue
    
    // Create a deep copy, resolving any references for values.
    // 创建一个深度拷贝,解析值的任何引用。
    List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    
    boolean resolveNecessary = false;
    for (PropertyValue pv : original) {
        if (pv.isConverted()) {
            //已经类型转换过了
            deepCopy.add(pv);
        }
        else {
            String propertyName = pv.getName();
            Object originalValue = pv.getValue();
            //标记位,实际使用resolveDependency方法查找依赖注入的对象
            if (originalValue == AutowiredPropertyMarker.INSTANCE) {
                //必须要提供写方法
                Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
                if (writeMethod == null) {
                    throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
                }
                //构建一个属性描述器
                originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
            }

            //2.1 解析对象
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

            //2.2 类型转换
            Object convertedValue = resolvedValue;
        	//是否可转换
            //	检查属性是否可写,必须有写方法(setter method)
            //	检查给定的属性路径是否指示索引或嵌套属性。比如user.name[0],这种就不行
            boolean convertible = bw.isWritableProperty(propertyName) &&
                    !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
            if (convertible) {
                //转换器转换后的值
                convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
            }

            //3. 缓存解析后的PropertyValue:resolvedValue -> convertedValue
            
            // Possibly store converted value in merged bean definition,
            // in order to avoid re-conversion for every created bean instance.

            //3.1 缓存情况1:解析后的对象实例没有被替换(地址匹配):如动态代理等,会直接替换对象。
            if (resolvedValue == originalValue) {
                if (convertible) {
                    //可转换的,记录转换后的值
                    pv.setConvertedValue(convertedValue);
                }
                deepCopy.add(pv);
            }
            //3.2 缓存情况2:如果是可转换的,对象类型是TypedStringValue且不需要动态转换、转换后不是集合或数组
            //	originalValue如果是TypedStringValue,则类型转换器会将String转换成指定类型targetType
            else if (convertible && originalValue instanceof TypedStringValue &&
                    !((TypedStringValue) originalValue).isDynamic() &&
                    !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                pv.setConvertedValue(convertedValue);
                deepCopy.add(pv);
            }
            //3.3 不缓存:每次都重新解析
            else {
                resolveNecessary = true;
                //最终的值放到deepCopy
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }

    //所有的字段都能成功解析,不会再变,才会标记mpvs为转换完成,否则下次还需要动态解析
    //也可能是mpvs包含的部分字段需要解析
    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }

    // Set our (possibly massaged) deep copy.
    try {
        //BeanWrapper属性注入
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {...}
}

BeanDefinitionValueResolver

BeanDefinitionValueResolver#resolveValueIfNecessary(argName, value) 方法功能:解析 value 的真实类型,value 的类型不同,处理的结果也不同。本质就是进行依赖查找。

  • RuntimeBeanReference 类型:引用类型,根据 ref.beanType 或 ref.beanName 从容器中获取。
  • RuntimeBeanNameReference 类型:Spring EL 表达式解析 ref.beanName。
  • BeanDefinitionHolder 或 BeanDefinition 类型:根据 BeanDefinition 实例化 bean。
  • DependencyDescriptor:采用 beanFactory#resolveDependency 进行依赖查找。
  • ManagedList 等集合类型:规则和上述完全类似,只是返回集合而已。
  • 其它类型:如果是 String,则 Spring EL 表达式解析,其余的直接返回 originalValue。

如 applyPropertyValues 中的 AutowiredPropertyMarker.INSTANCE 类型:表示使用 beanFactory#resolveDependency 进行依赖查找。BeanDefinitionBuilder 添加属性时就会使用时这些类型。
在这里插入图片描述

BeanWrapper属性注入

BeanWrapper:对 Bean 操作的封装,如 JavaBean 的内省,属性的设置。其 bw.setPropertyValues(mpvs) 将属性注入到 bean 实例中。

  • BeanWrapperImpl:(默认)采用 PropertyDescriptor 进行注入,也就是 setter 方法反射注入,对应的处理器为 BeanPropertyHandler。
  • DirectFieldAccessor:采用字段注入,对应的处理器为 FieldPropertyHandler。

核心代码:
org.springframework.beans.BeanWrapperImpl.BeanPropertyHandler#setValue

public void setValue(@Nullable Object value) throws Exception {
	Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
			((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
			this.pd.getWriteMethod());
	if (System.getSecurityManager() != null) {...}
	else {
		ReflectionUtils.makeAccessible(writeMethod);
		writeMethod.invoke(getWrappedInstance(), value);
	}
}

反射set方法赋值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring源码分析(八)依赖注入源码解析1:autowire自动注入 和 @Autowired注入 的相关文章

随机推荐