依赖注入流程图

Spring之依赖注入底层源码解析 - 图1

  1. 首先先去找到所有注入点,注入点分为两种: 被@Autowired注解了的属性 以及 被@Autowired注解了的方法
  2. 遍历每个注入点
  3. 根据注入点去找Bean,这里如果注解了属性的会根据属性的类型去找Bean,如果注解了的是方法,那就根据方法中的参数类型去找Bean
  4. 对于找到有几个Bean
  • 如果找到一个Bean,直接把这个Bean进行注入
  • 如果找到多个Bean,会从多个Bean中确定出一个Bean
    1. 先判断是不是isAutowiredCandidate
    2. 再判断是不是复合Qualifier
    3. 如果还有多个,取@Primary的Bean
    4. 取出优先级最高的Bean
    5. 根据名字进行筛选,筛选出唯一的Bean
      1. 如果是根据属性注入的,那么就是根据属性名字去找
      2. 如果是根据set方法,那就是参数名字
  • 如果没有找到Bean

如果@Autowired的reuqired属性为true,也就是说注入点必须被注入,那么就会报错

依赖注入的方式

对于Spring中依赖注入的方式,分为两种:

  • 手动注入
    • set方法注入
    • 构造方法注入
  • 自动注入

    • XML的autowire自动注入
    • @Autowired注解的自动注入

      手动注入

      在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定的值,下面这种底层是通过set方法进行注入
      1. <bean name="userService" class="linc.fun.service.UserService">
      2. <property name="orderService" ref="orderService"/>
      3. </bean>
      下面这种是通过构造方法进行注入
      1. <bean name="userService" class="linc.fun.service.UserService">
      2. <constructorarg index="0" ref="orderService"/>
      3. </bean>

      自动注入

      自动注入又分为两种
  • XML的autowire自动注入

  • @Autowired注解的自动注入

    XML的autowire自动注入

    在XML中,我们可以在定义一个Bean时去指定这个Bean的自动注入模式:

  • byType

  • byName
  • constructor
  • default
  • no

    1. <bean id="userService" class="linc.fun.service.UserService" autowire="byType"/>

    如果这么写,表示Spring会自动的给userService中所有的属性进行自动赋值,不需要在属性上加@Autowired注解,但需要这个属性有对应的set方法

    PropertyDescriptor对象

    在创建Bean的过程中,在填充属性时,Spring会去解析当前类,把当前类的所有方法都解析出来,Spring会解析每个方法得到对应的PropertyDescriptor对象,PropertyDescriptor有几个属性:

    1. public class PropertyDescriptor extends FeatureDescriptor {
    2. private Reference<? extends Class<?>> propertyTypeRef;
    3. private final MethodRef readMethodRef = new MethodRef();
    4. private final MethodRef writeMethodRef = new MethodRef();
    5. private Reference<? extends Class<?>> propertyEditorClassRef;
    6. private boolean bound;
    7. private boolean constrained;
    8. // The base name of the method name which will be prefixed with the
    9. // read and write method. If name == "foo" then the baseName is "Foo"
    10. private String baseName;
    11. private String writeMethodName;
    12. private String readMethodName;
    13. public PropertyDescriptor(String propertyName, Class<?> beanClass)
    14. throws IntrospectionException {
    15. this(propertyName, beanClass,
    16. Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName),
    17. Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));
    18. }
    19. .....
    20. }
    1. static final String GET_PREFIX = "get";
    2. static final String SET_PREFIX = "set";
    3. static final String IS_PREFIX = "is";
  1. name: 这个name并不是方法的名字,而是拿方法名字进行过处理后的名字
  • 如果方法名字以”get”开头,比如”getXXX”,那么name=XXX
  • 如果方法名字以”is”开头,比如”isXXX”,那么name=XXX
  • 如果方法名字以”set”开头,比如”setXXX”,那么name=XXX
  1. readMethodRef: 表示get方法的Method对象的引用
  2. readMethodName: 表示get方法的名字
  3. writeMethodRef: 表示set方法的Method对象的引用
  4. writeMethodName: 表示set方法的名字
  5. propertyTypeRef: 如果有get方法那么对应的就是返回值的类型,如果set方法那么对应的就是set方法中唯一参数的类型

    get,set方法的定义

    对于get方法的定义是: 方法参数个数为0,并且方法名字以”get”开头或者方法名字以”is”开头并且方法的返回类型为boolean
    对于set方法的定义是: 方法参数个数为1,并且方法以”set”开头并且方法返回类型为void

    byName自动填充属性时的流程

    Spring在通过byName的自动填充属性时的流程是:
  • 找到所有set方法所对应的XXX部分的名字
  • 根据XXX部分的名字去获取Bean

    byType的自动填充属性时的流程

  • 获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取Bean

  • 如果找到多个,会报错

    constructor注入

    以上,分析了autowire的byType和byName情况,那么接下来分析constructor,constructor表示通过构造方法注入,其实这种情况就比较简单了,没有byType和byName那么复杂
    如果是constructor,那么就可以不写set方法了,当某个Bean是通过构造方法来注入时,Spring利用构造方法的参数信息从Spring容器中去找Bean,找到Bean之后作为参数传给构造方法,从而实例化得到一个Bean对象,并完成属性赋值(属性赋值的代码需要程序员来实现)
    这里,我们只考虑只有一个有参数构造方法,其实构造方法注入相当于 byType+byName ,普通的byType是根据set方法的参数类型去找Bean,找到多个会报错,而constructor就是通过构造方法中的参数类型去找Bean,如果找到多个会根据参数名确定
    问:为什么选择使用@Autowired,而不用XML的形式呢?
    @Autowired注解相当于XML中的autowire属性的注解方式的替代
    官网如下解释: 从本质上将,@Autowired注解提供了与autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性

    Essentially, the @Autowired annotation provides the same capabilities as described in Autowiring Collaborators but with more fine‐grained control and wider applicability
    

    这里强调的是更细粒度的控制
    XML中的autowire控制的是整个Bean的所有属性,而@Autowired注解是直接写在某个属性上、某个set方法、某个构造方法上的
    倘若我们使用XML的形式,如果用XML中的autowire=constructor,在拥有多个构造方法的情况下,无法进行很好的控制,但是通过@Autowired注解可以直接指定想用哪个构造方法
    同时,用@Autowired注解,还可以控制哪些属性想被自动注入,哪些属性不想,这也是细粒度的控制
    但是@Autowird无法区分byType和byName,@Autowired是先byType,如果找到多个就会选择byName
    那么XML的自动注入底层其实也就是

  • set方法注入

  • 构造方法注入

    @Autowired注解的自动注入

    @Autowired注解是byType+byName的结合
    对于@Autowired注解可以有如下几种使用方式

  • 属性上: 先根据属性类型去找Bean,如果找到多个再根据属性名去确定一个

  • 构造方法: 现根据方法参数类型去找Bean,如果找到多个再根据参数名去确定一个
  • set方法上: 先根据方法参数类型去找Bean,如果找到多个再根据参数名去确定一个

对于底层到了

  • 属性注入
  • set方法注入
  • 构造方法注入

    寻找注入点

    在创建一个Bean的过程中,Spring会利用AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition找出注入点并且缓存

    /**
    *  实例化后的合并BeanDefinition之后的BeanDefinition进行处理
    *  找注入点
    */
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
      InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
      metadata.checkConfigMembers(beanDefinition);
    }
    
    /**
    * 寻找注入点,看哪些需要注入,哪些set方法上加了注解
    */
    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.
    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);
              }
              // 解析注入点并缓存
              metadata = buildAutowiringMetadata(clazz);
              this.injectionMetadataCache.put(cacheKey, metadata);
          }
      }
    }
    return metadata;
    }
    

    找注入点的流程

    private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
      // 如果一个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 -> {
              // field上是否存在@Autowired、@Value、@Inject中的其中一个
              MergedAnnotation<?> ann = findAutowiredAnnotation(field);
              if (ann != null) {
                  // static filed不是注入点,不会进行自动注入
                  // 在两个bean都是原型bean的情况下,其中一个是static bean注入,可能导致对象内部属性的值发生变化
                  if (Modifier.isStatic(field.getModifiers())) {
                      if (logger.isInfoEnabled()) {
                          logger.info("Autowired annotation is not supported on static fields: " + field);
                      }
                      return;
                  }
    
                  // 构造注入点
                  boolean required = determineRequiredStatus(ann);
                  currElements.add(new AutowiredFieldElement(field, required));
              }
          });
    
          // 遍历targetClass中的所有Method
          ReflectionUtils.doWithLocalMethods(targetClass, method -> {
              // 处理桥接方法 泛型的时候,字节码会有两个set方法
              Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
              if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                  return;
              }
              // method上是否存在@Autowired、@Value、@Inject中的其中一个
              MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
              if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                  // static method不是注入点,不会进行自动注入
                  if (Modifier.isStatic(method.getModifiers())) {
                      if (logger.isInfoEnabled()) {
                          logger.info("Autowired annotation is not supported on static methods: " + method);
                      }
                      return;
                  }
                  // set方法最好有入参,没有就会打印一条日志
                  if (method.getParameterCount() == 0) {
                      if (logger.isInfoEnabled()) {
                          logger.info("Autowired annotation should only be used on methods with parameters: " +
                                  method);
                      }
                  }
                  // 判断是否是required = true 如果是,但是没找到可以赋值给它就会报错,false就没事
                  boolean required = determineRequiredStatus(ann);
                  PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                  currElements.add(new AutowiredMethodElement(method, required, pd));
              }
          });
          // 父类的会放在最前面
          elements.addAll(0, currElements);
          targetClass = targetClass.getSuperclass(); // 找父类的
      }
      while (targetClass != null && targetClass != Object.class);
    
      // 返回并且缓存
      return InjectionMetadata.forElements(elements, clazz);
    }
    

    Spring之依赖注入底层源码解析 - 图2

  • 遍历当前类的所有的属性字段field

  • 查看字段上是否存在@Autowired、@Value、@Inject中其中任意一个,存在则认为该字段是一个注入点
  • 如果字段是static,则不进行注入
  • 获取@Autowired中的required属性的值
  • 将字段信息构建成一个AutowiredFieldElement对象,作为一个注入点对象添加到currElements集合中
  • 遍历当前类的所有方法Method
  • 判断当前Method是否存在桥接方法,如果是,找到原方法
  • 查看方法上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该方法是一个注入点
  • 如果方法是static的,则不进行注入
  • 获取@Autowired中的required属性的值
  • 将方法信息构造成一个AutowiredMethodElement对象,作为一个注入点对象添加到currElements集合中
  • 遍历完当前类的字段和方法后,将遍历父类的,直到没有父类
  • 最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合对象,并且缓存

    static的字段或方法为什么不支持依赖注入

    ```java @Component @Scope(“prototype”) public class CService { }

@Component @Scope(“prototype”) public class DService { @Autowired private static CService cService;

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

}

在CService和DService都是原型Bean的情况下,倘若Spring支持static字段进行自动注入,那么现在调用两次
```java
@Test
public void testPrototypeStatic() {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    DService d1 = ctx.getBean(DService.class);
    DService d2 = ctx.getBean(DService.class);
}

对于此时,d1的CService值是什么?还是它自己注入的值吗
很显然不是,一旦d2创建好了,static Cservice字段的值就发生了改变了,从而会出现bug

桥接方法

// class version 52.0 (52)
// access flags 0x21
// signature Ljava/lang/Object;Llinc/cool/service/UserInterface<Llinc/cool/service/OrderService;>;
// declaration: linc/cool/service/UserService implements linc.cool.service.UserInterface<linc.cool.service.OrderService>
public class linc/cool/service/UserService implements linc/cool/service/UserInterface {

  // compiled from: UserService.java

  // access flags 0x2
  private Llinc/cool/service/OrderService; orderService

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 10 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Llinc/cool/service/UserService; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public test()V
   L0
    LINENUMBER 13 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 0
    INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
    INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String;
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    LDC ".test()"
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 14 L1
    RETURN
   L2
    LOCALVARIABLE this Llinc/cool/service/UserService; L0 L2 0
    MAXSTACK = 3
    MAXLOCALS = 1

  // access flags 0x1
  public setOrderService(Llinc/cool/service/OrderService;)V
  @Lorg/springframework/beans/factory/annotation/Autowired;()
   L0
    LINENUMBER 22 L0
    ALOAD 0
    ALOAD 1
    PUTFIELD linc/cool/service/UserService.orderService : Llinc/cool/service/OrderService;
   L1
    LINENUMBER 24 L1
    RETURN
   L2
    LOCALVARIABLE this Llinc/cool/service/UserService; L0 L2 0
    LOCALVARIABLE orderService Llinc/cool/service/OrderService; L0 L2 1
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x1041 桥接方法
  public synthetic bridge setOrderService(Ljava/lang/Object;)V
  @Lorg/springframework/beans/factory/annotation/Autowired;()
   L0
    LINENUMBER 10 L0
    ALOAD 0
    ALOAD 1
    CHECKCAST linc/cool/service/OrderService
    INVOKEVIRTUAL linc/cool/service/UserService.setOrderService (Llinc/cool/service/OrderService;)V
    RETURN
   L1
    LOCALVARIABLE this Llinc/cool/service/UserService; L0 L1 0
    MAXSTACK = 2
    MAXLOCALS = 2
}

可以看到UserService的字节码中有两个setOrderService方法

public setOrderService(Llinc/cool/service/OrderService;)V
public synthetic bridge setOrderService(Ljava/lang/Object;)V

并且都是存在@Autowired注解的,所以在Spring中需要处理这种情况,当遍历到桥接方法时,得找到原方法

注入点进行注入

Spring在AutowiredAnnotationBeanPostProcessor#postProcessProperties方法中,会遍历所找到的注入点依次进行注入

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 找注入点(所有被@Autowired注解了的Field或Method) 此时已经可以直接从缓存中拿出来了
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 给字段赋值,给方法参数赋值
        metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}
/**
 * 注入
 */
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);
        }
    }
}

字段注入

private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
    ...
    /**
     * 字段的注入
     */
    @Override
    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        // 这里没有进行判断Pvs有没有,和method有点区别
        Field field = (Field) this.member;
        Object value;
        if (this.cached) {
            // 对于原型Bean,第一次创建的时候,也找注入点,然后进行注入,此时cached为false,注入完了之后cached为true
            // 第二次创建的时候,先找注入点(此时会拿到缓存好的注入点),也就是AutowiredFieldElement对象,此时cache为true,也就进到此处了
            // 注入点内并没有缓存被注入的具体Bean对象,而是beanName,这样就能保证注入到不同的原型Bean对象
            try {
                value = resolvedCachedArgument(beanName, this.cachedFieldValue);
            } catch (NoSuchBeanDefinitionException ex) {
                // Unexpected removal of target bean for cached argument -> re-resolve
                value = resolveFieldValue(field, bean, beanName);
            }
        } else {
            // 根据filed从BeanFactory中查到的匹配的Bean对象
            value = resolveFieldValue(field, bean, beanName);
        }
        // 反射给filed赋值
        if (value != null) {
            ReflectionUtils.makeAccessible(field);
            field.set(bean, value);
        }
    }
}
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
    DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
    desc.setContainingClass(bean.getClass());
    Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
    Assert.state(beanFactory != null, "No BeanFactory available");
    TypeConverter typeConverter = beanFactory.getTypeConverter();
    Object value;
    try {
        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    } catch (BeansException ex) {
        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    }
    synchronized (this) {
        if (!this.cached) {
            Object cachedFieldValue = null;
            if (value != null || this.required) {
                cachedFieldValue = desc;
                // 注册一下beanName依赖了autowiredBeanNames,
                registerDependentBeans(beanName, autowiredBeanNames);
                if (autowiredBeanNames.size() == 1) {
                    String autowiredBeanName = autowiredBeanNames.iterator().next();
                    if (beanFactory.containsBean(autowiredBeanName) &&
                            beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                        // 构造一个ShortcutDependencyDescriptor作为缓存,保存了当前filed所匹配的autowiredBeanName,而不是对应的bean对象 (考虑原型bean)
                        cachedFieldValue = new ShortcutDependencyDescriptor(
                                desc, autowiredBeanName, field.getType());
                    }
                }
            }
            this.cachedFieldValue = cachedFieldValue;
            this.cached = true;
        }
    }
    return value;
}
  • 遍历所有的AutowiredFieldElement对象
  • 将对应的字段封装为DependencyDescriptor对象
  • 调用BeanFactory#resolveDependency方法,传入DependencyDescriptor对象,进行依赖查找,找到当前字段所匹配的Bean对象
  • 将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortCutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该对象时,就可以拿缓存的结果对象beanName去BeanFactory中去拿Bean对象了,不用再次去进行查找
  • 利用反射将结果赋值给对象的字段

    Set方法注入

    private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
      ...
      @Override
      protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
          // 如果pvs中已经有当前注入点的值了,则跳过注入 看属性描述器中对应属性的名字在不在pvs里,在就跳过
          if (checkPropertySkipping(pvs)) {
              return;
          }
          Method method = (Method) this.member;
          Object[] arguments;
          // 找值的
          // 第一次注入是没有缓存的
          if (this.cached) {
              try {
                  arguments = resolveCachedArguments(beanName);
              } catch (NoSuchBeanDefinitionException ex) {
                  // Unexpected removal of target bean for cached argument -> re-resolve
                  arguments = resolveMethodArguments(method, bean, beanName);
              }
          } else {
              arguments = resolveMethodArguments(method, bean, beanName);
          }
          if (arguments != null) {
              try {
                  ReflectionUtils.makeAccessible(method);
                  method.invoke(bean, arguments);
              } catch (InvocationTargetException ex) {
                  throw ex.getTargetException();
              }
          }
      }
    }
    
    @Nullable
    private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String b
      // 方法参数个数
      int argumentCount = method.getParameterCount();
      // 保存参数对应的Bean对象
      Object[] arguments = new Object[argumentCount];
      // 有几个方法参数就有几个依赖描述器
      DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
      Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
      Assert.state(beanFactory != null, "No BeanFactory available");
      TypeConverter typeConverter = beanFactory.getTypeConverter();
      // 遍历每个方法参数,找到匹配的bean对象
      for (int i = 0; i < arguments.length; i++) {
          MethodParameter methodParam = new MethodParameter(method, i);
          // this.required: 是不是一定要赋值
          DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.req
          currDesc.setContainingClass(bean.getClass());
          descriptors[i] = currDesc;
          try {
              Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBe
              if (arg == null && !this.required) {
                  arguments = null;
                  break;
              }
              arguments[i] = arg;
          } catch (BeansException ex) {
              throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoin
          }
      }
      synchronized (this) {
          if (!this.cached) {
              if (arguments != null) {
                  DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descripto
                  registerDependentBeans(beanName, autowiredBeans);
                  if (autowiredBeans.size() == argumentCount) {
                      Iterator<String> it = autowiredBeans.iterator();
                      Class<?>[] paramTypes = method.getParameterTypes();
                      for (int i = 0; i < paramTypes.length; i++) {
                          String autowiredBeanName = it.next();
                          if (beanFactory.containsBean(autowiredBeanName) &&
                                  beanFactory.isTypeMatch(autowiredBeanName, paramTypes[
                              cachedMethodArguments[i] = new ShortcutDependencyDescripto
                                      descriptors[i], autowiredBeanName, paramTypes[i]);
                          }
                      }
                  }
                  this.cachedMethodArguments = cachedMethodArguments;
              } else {
                  this.cachedMethodArguments = null;
              }
              this.cached = true;
          }
      }
      return arguments;
    }
    
  • 遍历所有的AutowiredMethodElement对象

  • 遍历将对应的方法的参数,将每个参数封装成MethodParameter对象
  • 将MethodParameter对象封装成DependencyDescriptor对象
  • 调用BeanFactory#resolveDependency方法,传入DependencyDescriptor对象,进行依赖查找,摘到当前方法参数所匹配的Bean对象
  • 将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建对象时,就可以直接拿缓存的结果对象beanName去BeanFactory中去拿Bean对象了,不用再次去进行查找
  • 利用反射将找到的所有结果对象传给当前方法,并且执行

    注入点注入流程

    Spring之依赖注入底层源码解析 - 图3

    BeanFactory#resolveDependency

    @Nullable
    Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
          @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
    
    该方法表示,传入一个依赖描述DependencyDescriptor,该方法会根据依赖描述从BeanFactory中找出对应的唯一的一个Bean对象
    我们可以分析一下BeanFactory的实现类DefaultListableBeanFactory#resolveDependency方法的具体实现

    Spring中根据类型找Bean的底层流程

    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable St
          @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typ
      // 用来获取方法入参名字的
      descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
      // 所需要的类型是Optional
      if (Optional.class == descriptor.getDependencyType()) {
          return createOptionalDependency(descriptor, requestingBeanName);
      }
      // 所需要的的类型是ObjectFactory,或ObjectProvider
      else if (ObjectFactory.class == descriptor.getDependencyType() ||
              ObjectProvider.class == descriptor.getDependencyType()) {
          return new DependencyObjectProvider(descriptor, requestingBeanName);
      }
      else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
          return new Jsr330Factory().createDependencyProvider(descriptor, reque
      }
      else {
          // 在属性或set方法上使用了@Lazy注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选Bean
          Object result = getAutowireCandidateResolver().getLazyResolutionProxy
                  descriptor, requestingBeanName);
          if (result == null) {
              // descriptor表示某个属性或某个set方法
              // requestingBeanName表示正在进行依赖注入的Bean
              result = doResolveDependency(descriptor, requestingBeanName, auto
          }
          return result;
      }
    }
    
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
          @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansExce
      InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
      try {
          // 如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存
          Object shortcut = descriptor.resolveShortcut(this);
          if (shortcut != null) {
              return shortcut;
          }
          Class<?> type = descriptor.getDependencyType();
          // 获取@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);
                  // 解析Spring表达式(#{})
                  value = evaluateBeanDefinitionString(strVal, bd);
              }
              // 将value转化为descriptor所对应的类型 如果想让123赋值给一个对象,默认是做不了的,需要类型转换器
              TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
              try {
                  return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
              }
              catch (UnsupportedOperationException ex) {
                  // A custom TypeConverter which does not support TypeDescriptor resolution...
                  return (descriptor.getField() != null ?
                          converter.convertIfNecessary(value, type, descriptor.getField()) :
                          converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
              }
          }
          // 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的所有bean方法,不用进一步做筛选了
          Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConvert
          if (multipleBeans != null) {
              return multipleBeans;
          }
          // 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass --> 比较核心
          Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
          // 找到的Bean是空的->expected at least 1 bean which qualifies as autowire candidate
          if (matchingBeans.isEmpty()) {
              // required为true,抛异常
              if (isRequired(descriptor)) {
                  raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
              }
              return null;
          }
          String autowiredBeanName;
          Object instanceCandidate;
          // 找到了多个
          if (matchingBeans.size() > 1) {
              // 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name
              autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
              if (autowiredBeanName == null) {
                  if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                      return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                  }
                  else {
                      // In case of an optional Collection/Map, silently ignore a non-unique case:
                      // possibly it was meant to be an empty collection of multiple regular beans
                      // (before 4.3 in particular when we didn't even look for collection beans).
                      return null;
                  }
              }
              instanceCandidate = matchingBeans.get(autowiredBeanName);
          }
          else {
              // 只有一个
              // We have exactly one match.
              Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
              autowiredBeanName = entry.getKey();
              instanceCandidate = entry.getValue();
          }
          // 记录匹配过的beanName
          if (autowiredBeanNames != null) {
              autowiredBeanNames.add(autowiredBeanName);
          }
          // 有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean
          if (instanceCandidate instanceof Class) {
              instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
          }
          Object result = instanceCandidate;
          // @Bean的时候返回的是null,最后放到单例池的是NullBean
          if (result instanceof NullBean) {
              if (isRequired(descriptor)) {
                  raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
              }
              result = null;
          }
          if (!ClassUtils.isAssignableValue(type, result)) {
              throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass(
          }
          return result;
      }
      finally {
          ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
      }
    }
    
    ```java

@Nullable private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanNam @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) { Class<?> type = descriptor.getDependencyType(); if (descriptor instanceof StreamDependencyDescriptor) { // 找到type所匹配的所有bean Map matchingBeans = findAutowireCandidates(beanName, type, descriptor if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } // 构造成一个stream Stream stream = matchingBeans.keySet().stream() .map(name -> descriptor.resolveCandidate(name, type, this)) .filter(bean -> !(bean instanceof NullBean)); // 排序 if (((StreamDependencyDescriptor) descriptor).isOrdered()) { stream = stream.sorted(adaptOrderComparator(matchingBeans)); } return stream; } else if (type.isArray()) { // 得到数组元素的类型 Class<?> componentType = type.getComponentType(); ResolvableType resolvableType = descriptor.getResolvableType(); Class<?> resolvedArrayType = resolvableType.resolve(type); if (resolvedArrayType != type) { componentType = resolvableType.getComponentType().resolve(); } if (componentType == null) { return null; } // 根据数组元素类型找到所匹配的所有Bean Map matchingBeans = findAutowireCandidates(beanName, componentType, new MultiElementDescriptor(descriptor)); if (matchingBeans.isEmpty()) { return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } // 进行类型转化 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter() Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayTyp if (result instanceof Object[]) { Comparator comparator = adaptDependencyComparator(matchingBeans); if (comparator != null) { Arrays.sort((Object[]) result, comparator); } } return result; } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric() if (elementType == null) { return null; } Map matchingBeans = findAutowireCandidates(beanName, elementType, new MultiElementDescriptor(descriptor)); if (matchingBeans.isEmpty()) { return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter() Object result = converter.convertIfNecessary(matchingBeans.values(), type); if (result instanceof List) { if (((List<?>) result).size() > 1) { Comparator comparator = adaptDependencyComparator(matchingBeans); if (comparator != null) { ((List<?>) result).sort(comparator); } } } return result; } else if (Map.class == type) { ResolvableType mapType = descriptor.getResolvableType().asMap(); Class<?> keyType = mapType.resolveGeneric(0); // 如果Map的key不是String if (String.class != keyType) { return null; } Class<?> valueType = mapType.resolveGeneric(1); if (valueType == null) { return null; } Map matchingBeans = findAutowireCandidates(beanName, valueType, new MultiElementDescriptor(descriptor)); if (matchingBeans.isEmpty()) { return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } return matchingBeans; } else { return null; } }

![](https://cdn.nlark.com/yuque/0/2022/webp/25761560/1651579493852-40510af1-8e46-4ef8-9788-54f0ac14e140.webp#clientId=u4930ac04-33a0-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u16085b2d&margin=%5Bobject%20Object%5D&originHeight=1672&originWidth=1304&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u83553277-0c06-4d0b-89ec-0cb6352acb8&title=)

1. 调用DefaultListableBeanFactory#resolveDependency
- 判断依赖的类型
   1. 如果是Optional,调用doResolveDependency
   1. 如果是ObjectFactory或ObjectProvider,在调用ObjectFactory#getObject方法时调用doResolveDependency
   1. 如果依赖上有@Lazy注解.那么就会生成一个代理对象然后返回,那么在调用代理对象中的方法时调用doResolveDependency

2.  对于上面的doResolveDependency执行逻辑如下

- 判断是否存在@Value注解
   1. 如果存在,获取并且解析descriptor上的@Value注解,进行解析后并且返回
   1. 判断descriptor的类型
      1. 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的方法不用进一步做筛选了
      1. 调用findAutowireCandidate,findAutowireCandidate该方法会返回一个Map,表示会根据类型去找Bean,Map的key为beanName,Map的value为对象,对于value可能是Bean对象也可能是某Bean的class对象,因为该方法只负责根据类型找到对应的Bean,如果该Bean还没有实例化,那么该方法不负责去实例化,只会返回Bean对应的Class对象,表示这个Bean也是结果之一
      1. 根据类型看有没有找到Bean
         1. 如果找到了只有一个,就直接返回该Bean,如果是Class对象,就会调用getBean生成该Bean对象
         1. 如果超过一个
            1. 从多个Bean中选择被@Primary标注了的Bean,如果有多个@Primary会报错
            1. 如果没有@Primary,那么就看Bean上是否通过@Priority定义了优先级,如果定义了就获取优先级最高的Bean
            1. 如果没有优先级,那么就使用descriptor.getDependencyName来确定唯一的Bean
               1. 是否找出唯一的一个Bean
                  1. 找出了,也会判断是否是Class对象,如果是,就调用getBean方法去生成Bean对象,然后返回
                  1. 如果没找到,判断isReuquired如果是true就报错,否则返回null
      4. 如果没找到,判断isReuquired如果是true就报错,否则返回null
<a name="lHvNl"></a>
## DefaultListableBeanFactory#findAutowireCandidates
<a name="eIQcR"></a>
### Spring中根据类型找beanName底层流程
```java
    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this, requiredType, true, descriptor.isEager());
public static String[] beanNamesForTypeIncludingAncestors(
        ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
    Assert.notNull(lbf, "ListableBeanFactory must not be null");
    // 从本容器中找
    String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
    // 从父容器找并放入result
    if (lbf instanceof HierarchicalBeanFactory) {
        HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
        if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
            String[] parentResult = beanNamesForTypeIncludingAncestors(
                    (ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
            result = mergeNamesWithParent(result, parentResult, hbf);
        }
    }
    return result;
}
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
    // 如果没有冻结,就根据类型去BeanFactory找,如果冻结了,可能就跳过这个if然后去缓存中去拿了
    if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
        return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
    }
    // 把当前类型所匹配的beanName缓存起来
    Map<Class<?>, String[]> cache =
            (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
    String[] resolvedBeanNames = cache.get(type);
    if (resolvedBeanNames != null) {
        return resolvedBeanNames;
    }
    resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
    if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
        cache.put(type, resolvedBeanNames);
    }
    return resolvedBeanNames;
}
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
    List<String> result = new ArrayList<>();
    // Check all bean definitions.
    // 遍历所有的BeanDefinitions
    for (String beanName : this.beanDefinitionNames) {
        // Only consider bean as eligible if the bean name is not defined as alias for some other bean.
        if (!isAlias(beanName)) {
            try {
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // Only check bean definition if it is complete.
                // 判断mbd允不允许获取对应类型
                // 首先mdb不能是抽象的,然后allowEagerInit为true,则直接去推测mdb的类型,并进行匹配
                // 如果allowEagerInit为false,那就继续判断,如果mdb还没有加载类并且是懒加载的并且不允许提前加载类,那mbd不能用来进行匹配(因为不允许提前加载类,只能在此mdb自己去创建bean对象时
                // 如果allowEagerInit为false,并且mbd已经加载类了,或者是非懒加载的,或者允许提前加载类,并且不用必须提前初始化才能获取类型,那么就可以去进行匹配了
                // 这个条件有点复杂,但是如果只考虑大部分流程,则可以忽略这个判断,因为allowEagerInit传进来的基本上都是true
                if (!mbd.isAbstract() && (allowEagerInit ||
                        (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
                                !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                    boolean isFactoryBean = isFactoryBean(beanName, mbd);
                    BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
                    boolean matchFound = false;
                    boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
                    boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());
                    // 当前BeanDefinition不是FactoryBean,就是普通Bean
                    if (!isFactoryBean) {
                        // 在筛选Bean时,如果仅仅只包括单例,但是beanName对应的又不是单例,则忽略
                        if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                    } else {
                        if (includeNonSingletons || isNonLazyDecorated ||
                                (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                        if (!matchFound) {
                            // In case of FactoryBean, try to match FactoryBean instance itself next.
                            beanName = FACTORY_BEAN_PREFIX + beanName;
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                    }
                    if (matchFound) {
                        result.add(beanName);
                    }
                }
            } catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
                if (allowEagerInit) {
                    throw ex;
                }
                // Probably a placeholder: let's ignore it for type matching purposes.
                LogMessage message = (ex instanceof CannotLoadBeanClassException ?
                        LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) :
                        LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName));
                logger.trace(message, ex);
                // Register exception, in case the bean was accidentally unresolvable.
                onSuppressedException(ex);
            } catch (NoSuchBeanDefinitionException ex) {
                // Bean definition got removed while we were iterating -> ignore.
            }
        }
    }
}

Spring之依赖注入底层源码解析 - 图4

  • 找出BeanFactory中类型为type的所有bean的名字,注意的是名字而不是bean对象,因为我们可以根据BeanDefinition就能判断和当前type是不是匹配,不用生成Bean对象
  • 把resolvableDependencies中key为type的对象找出来并且添加到result中
  • 遍历根据type找出beanName,判断当前beanName对应的Bean是不是能够被自动注入
  • 先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果是false,表示不能用来进行自动注入,如果是true,就继续进行判断
  • 判断的当前type是不是泛型,如果是泛型,会把容器中所有的beanName找出来,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么就继续判断
  • 如果当前DependencyDescriptor上存在@Qualifier注解,那么就要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等就匹配
  • 经过上述验证后,当前beanName才能成为一个可注入的,添加到result中

    依赖注入流程

    Spring之依赖注入底层源码解析 - 图5

    依赖注入中泛型注入的实现

    首先在Java反射中,有一个Type接口,表示类型,具体分类为:
  1. raw types:也就是普通Class
  2. parameterized types:对应ParameterizedType接口,泛型类型
  3. array types:对应GenericArrayType,泛型数组
  4. type variables:对应TypeVariable接口,表示类型变量,也就是所定义的泛型,比如T、K
  5. primitive types:基本类型,int、boolean

我们可以看下下面的打印结果:

public class TypeTest<T> {

 private int i;
 private Integer it;
 private int[] iarray;
 private List list;
 private List<String> slist;
 private List<T> tlist;
 private T t;
 private T[] tarray;

 public static void main(String[] args) throws NoSuchFieldException {

        test(TypeTest.class.getDeclaredField("i"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("it"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("iarray"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("list"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("slist"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("tlist"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("t"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("tarray"));

    }

 public static void test(Field field) {

  if (field.getType().isPrimitive()) {
            System.out.println(field.getName() + "是基本数据类型");
        } else {
            System.out.println(field.getName() + "不是基本数据类型");
        }

  if (field.getGenericType() instanceof ParameterizedType) {
            System.out.println(field.getName() + "是泛型类型");
        } else {
            System.out.println(field.getName() + "不是泛型类型");
        }

  if (field.getType().isArray()) {
            System.out.println(field.getName() + "是普通数组");
        } else {
            System.out.println(field.getName() + "不是普通数组");
        }

  if (field.getGenericType() instanceof GenericArrayType) {
            System.out.println(field.getName() + "是泛型数组");
        } else {
            System.out.println(field.getName() + "不是泛型数组");
        }

  if (field.getGenericType() instanceof TypeVariable) {
            System.out.println(field.getName() + "是泛型变量");
        } else {
            System.out.println(field.getName() + "不是泛型变量");
        }
    }
}
i是基本数据类型
i不是泛型类型
i不是普通数组
i不是泛型数组
i不是泛型变量
=======
it不是基本数据类型
it不是泛型类型
it不是普通数组
it不是泛型数组
it不是泛型变量
=======
iarray不是基本数据类型
iarray不是泛型类型
iarray是普通数组
iarray不是泛型数组
iarray不是泛型变量
=======
list不是基本数据类型
list不是泛型类型
list不是普通数组
list不是泛型数组
list不是泛型变量
=======
slist不是基本数据类型
slist是泛型类型
slist不是普通数组
slist不是泛型数组
slist不是泛型变量
=======
tlist不是基本数据类型
tlist是泛型类型
tlist不是普通数组
tlist不是泛型数组
tlist不是泛型变量
=======
t不是基本数据类型
t不是泛型类型
t不是普通数组
t不是泛型数组
t是泛型变量
=======
tarray不是基本数据类型
tarray不是泛型类型
tarray是普通数组
tarray是泛型数组
tarray不是泛型变量

在Spring中,如果注入点是泛型,也是会进行处理的

@Component
public class UserService extends BaseService<OrderService, StockService> {

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

}

public class BaseService<O, S> {

 @Autowired
 protected O o;

 @Autowired
 protected S s;
}
  • Spring扫描时发现UserService是一个Bean
  • 那就取出注入点,也就是BaseService中的两个属性o和s
  • 接下来需要按注入点类型进行注入,但是o和s都是泛型,所以Spring需要确定o和s的具体类型
  • 因为当前正在创建的是UserService的Bean,所以可以通过userService.getClass().getGenericSuperclass().getTypeName()获取到具体的泛型信息
  • 然后再拿到UserService的父类BaseServuce泛型变量

    for (TypeVariable<? extends Class<?>> typeParameter : userService.getClass().getSuperclass().getTypeParameters()) {             System._out_.println(typeParameter.getName()); 
    }
    
  • 通过上面两段代码,就能知道,o对应的具体就是OrderService,s对应的具体类型就是StockService

  • 然后再调用oField.getGenericType()就知道当前field使用的是哪个泛型,就能知道具体类型了

    Qualifier的使用

    我们可以模拟实现负载均衡 ```java @Target({ElementType.TYPE, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Qualifier(“random”) public @interface Random { }

@Target({ElementType.TYPE, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Qualifier(“roundRobin”) public @interface RoundRobin { }

public interface LoadBalance { String select(); }

@Component @Random public class RandomStrategy implements LoadBalance {

@Override public String select() { return null; } }

@Component @RoundRobin public class RoundRobinStrategy implements LoadBalance {

@Override public String select() { return null; } }

**使用**
```java
@Component
public class UserService  {

 @Autowired
 @RoundRobin
 private LoadBalance loadBalance;

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

@Resource

@Resource注解底层工作流程图
Spring之依赖注入底层源码解析 - 图6
对于@Resouce的具体实现CommonAnnotationBeanPostProcessor#postProcessProperties

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    try {
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    }
    return pvs;
}