Spring杂谈 | Spring中的AutowireCandidateResolver

简介: Spring杂谈 | Spring中的AutowireCandidateResolver

接口定义


用于推断一个特定的beanDefinition是否能作为指定依赖的候选者的策略接口

public interface AutowireCandidateResolver {
  // 默认情况下直接根据bd中的定义返回,如果没有进行特殊配置的话为true
  default boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    return bdHolder.getBeanDefinition().isAutowireCandidate();
  }
    // 指定的依赖是否是必要的
  default boolean isRequired(DependencyDescriptor descriptor) {
    return descriptor.isRequired();
  }
    // QualifierAnnotationAutowireCandidateResolver做了实现,判断是否有@Qualifier注解
    // 一共有两种注解:
    // 1.Spring内置的@Qualifier注解,org.springframework.beans.factory.annotation.Qualifier
    // 2.添加了JSR-330相关依赖,javax.inject.Qualifier注解
    // 默认情况下返回false
  default boolean hasQualifier(DependencyDescriptor descriptor) {
    return false;
  }
    // QualifierAnnotationAutowireCandidateResolver做了实现
    // 获取一个该依赖一个建议的值
  @Nullable
  default Object getSuggestedValue(DependencyDescriptor descriptor) {
    return null;
  }
    // 对某个依赖我们想要延迟注入,但是在创建Bean的过程中这个依赖又是必须的
    // 通过下面这个方法就能为延迟注入的依赖先生成一个代理注入到bean中
  @Nullable
  default Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
    return null;
  }
}

继承关系


微信图片_20221113143501.png


可以看到继承关系都是单层的,我们就一个一个往下看


SimpleAutowireCandidateResolver


相比于接口没有什么区别,实现也就是父接口中的默认实现,一般也不会使用这个类

public class SimpleAutowireCandidateResolver implements AutowireCandidateResolver {
  @Override
  public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    return bdHolder.getBeanDefinition().isAutowireCandidate();
  }
  @Override
  public boolean isRequired(DependencyDescriptor descriptor) {
    return descriptor.isRequired();
  }
  @Override
  @Nullable
  public Object getSuggestedValue(DependencyDescriptor descriptor) {
    return null;
  }
  @Override
  @Nullable
  public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
    return null;
  }
}

GenericTypeAwareAutowireCandidateResolver


额外增加了对泛型的处理能力

public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCandidateResolver
    implements BeanFactoryAware {
  @Nullable
  private BeanFactory beanFactory;
  @Override
  public void setBeanFactory(BeanFactory beanFactory) {
    this.beanFactory = beanFactory;
  }
  @Nullable
  protected final BeanFactory getBeanFactory() {
    return this.beanFactory;
  }
  @Override
  public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    if (!super.isAutowireCandidate(bdHolder, descriptor)) {
      // 如果bd中已经配置了这个bean不做为依赖进行注入的话,直接返回false
      return false;
    }
        // 检查泛型是否匹配
    return checkGenericTypeMatch(bdHolder, descriptor);
  }
}

QualifierAnnotationAutowireCandidateResolver


增加了对@Qualifier注解以及@Value注解的处理能力

public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver {
  private final Set<Class<? extends Annotation>> qualifierTypes = new LinkedHashSet<>(2);
  // @Value注解
  private Class<? extends Annotation> valueAnnotationType = Value.class;
    // @Qualifier注解
  @SuppressWarnings("unchecked")
  public QualifierAnnotationAutowireCandidateResolver() {
    this.qualifierTypes.add(Qualifier.class);
    try {
      this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Qualifier",
              QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
    }
    catch (ClassNotFoundException ex) {
      // JSR-330 API not available - simply skip.
    }
  }
  // .......
  @Override
  public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
        // 类型上已经匹配了
    boolean match = super.isAutowireCandidate(bdHolder, descriptor);
    if (match) {
            // 还需要判断是否满足@Qualifier注解的要求
      match = checkQualifiers(bdHolder, descriptor.getAnnotations());
      if (match) {
        MethodParameter methodParam = descriptor.getMethodParameter();
        if (methodParam != null) {
          Method method = methodParam.getMethod();
          if (method == null || void.class == method.getReturnType()) {
            match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
          }
        }
      }
    }
    return match;
  }
  // .....
    // 是否是@Qualifier注解
  protected boolean isQualifier(Class<? extends Annotation> annotationType) {
    for (Class<? extends Annotation> qualifierType : this.qualifierTypes) {
      if (annotationType.equals(qualifierType) || annotationType.isAnnotationPresent(qualifierType)) {
        return true;
      }
    }
    return false;
  }
  @Override
  @Nullable
  public Object getSuggestedValue(DependencyDescriptor descriptor) {
    Object value = findValue(descriptor.getAnnotations());
    if (value == null) {
      MethodParameter methodParam = descriptor.getMethodParameter();
      if (methodParam != null) {
        value = findValue(methodParam.getMethodAnnotations());
      }
    }
    return value;
  }
    // 查找@Value注解
  @Nullable
  protected Object findValue(Annotation[] annotationsToSearch) {
    if (annotationsToSearch.length > 0) {   
      AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(
          AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);
      if (attr != null) {
        return extractValue(attr);
      }
    }
    return null;
  }
    // 获取@Value注解中的值
  protected Object extractValue(AnnotationAttributes attr) {
    Object value = attr.get(AnnotationUtils.VALUE);
    if (value == null) {
      throw new IllegalStateException("Value annotation must have a value attribute");
    }
    return value;
  }
}

ContextAnnotationAutowireCandidateResolver


这个类是最底层的子类,集成了所有的方法,并且额外提供了对依赖进行延迟处理的能力

public class ContextAnnotationAutowireCandidateResolver extends QualifierAnnotationAutowireCandidateResolver {
    // 如果依赖需要进行延迟处理,那么构建一个代理对象先注入到bean中,不会直接去创建依赖对象
  @Override
  @Nullable
  public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
    return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
  }
    // 依赖是否需要延迟处理
  protected boolean isLazy(DependencyDescriptor descriptor) {
    for (Annotation ann : descriptor.getAnnotations()) {
      Lazy lazy = AnnotationUtils.getAnnotation(ann, Lazy.class);
      if (lazy != null && lazy.value()) {
        return true;
      }
    }
    MethodParameter methodParam = descriptor.getMethodParameter();
    if (methodParam != null) {
      Method method = methodParam.getMethod();
      if (method == null || void.class == method.getReturnType()) {
        Lazy lazy = AnnotationUtils.getAnnotation(methodParam.getAnnotatedElement(), Lazy.class);
        if (lazy != null && lazy.value()) {
          return true;
        }
      }
    }
    return false;
  }
    // 构建延迟处理的代理对象
  protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
    final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
        // 创建了一个TargetSource
    TargetSource ts = new TargetSource() {
      @Override
      public Class<?> getTargetClass() {
        return descriptor.getDependencyType();
      }
      @Override
      public boolean isStatic() {
        return false;
      }
            // target是我们实际想要使用的对象,如果不进行延迟处理,那么注入到bean中的应该就是这个对象
            // 但是因为要进行延迟注入依赖,所有会向外暴露一个TargetSource,这个TargetSource的目标为实际想要使用的对象,生成代理时会基于TargetSource进行生成。在运行期间(完成注入后)我们使用这个延迟处理的依赖时实际调用的会是target中的方法。
      @Override
      public Object getTarget() {
        Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
        if (target == null) {
          Class<?> type = getTargetClass();
          if (Map.class == type) {
            return Collections.emptyMap();
          }
          else if (List.class == type) {
            return Collections.emptyList();
          }
          else if (Set.class == type || Collection.class == type) {
            return Collections.emptySet();
          }
          throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
              "Optional dependency not present for lazy injection point");
        }
        return target;
      }
      @Override
      public void releaseTarget(Object target) {
      }
    };
        // 使用ProxyFactory,给TargetSource生成一个代理
    ProxyFactory pf = new ProxyFactory();
    pf.setTargetSource(ts);
    Class<?> dependencyType = descriptor.getDependencyType();
        // 如果依赖的类型是一个接口,需要让代理类也实现这个接口
    if (dependencyType.isInterface()) {
      pf.addInterface(dependencyType);
    }
        // 生成代理
    return pf.getProxy(beanFactory.getBeanClassLoader());
  }
}

总结


  • SimpleAutowireCandidateResolver:单纯的将接口变成了可实例化的类,方法实现跟接口保持一致
  • GenericTypeAwareAutowireCandidateResolver: 判断泛型是否匹配,支持泛型依赖注入(From Spring4.0)
  • QualifierAnnotationAutowireCandidateResolver :处理 @Qualifier 和 @Value 注解
  • ContextAnnotationAutowireCandidateResolver :处理依赖级别的 @Lazy 注解,重写了getLazyResolutionProxyIfNecessary 方法。


相关文章
|
Java Spring
Spring依赖注入(DI)核心接口AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理【享学Spring】(下)
Spring依赖注入(DI)核心接口AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理【享学Spring】(下)
Spring依赖注入(DI)核心接口AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理【享学Spring】(下)
|
Java Spring 容器
Spring依赖注入(DI)核心接口AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理【享学Spring】(上)
Spring依赖注入(DI)核心接口AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理【享学Spring】(上)
Spring依赖注入(DI)核心接口AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理【享学Spring】(上)
|
搜索推荐 Java API
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(下)
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(下)
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(下)
|
XML Java 数据格式
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(中)
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(中)
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(中)
|
IDE Java 开发工具
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(上)
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(上)
【小家Spring】Spring标准处理组件大合集(ParameterNameDiscoverer、AutowireCandidateResolver、ResolvableType。。。)(上)
|
缓存 Java Spring
Spring依赖注入(DI)核心接口AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理【享学Spring】(中)
Spring依赖注入(DI)核心接口AutowireCandidateResolver深度分析,解析@Lazy、@Qualifier注解的原理【享学Spring】(中)
|
21天前
|
Java 测试技术 数据库
Spring Boot中的项目属性配置
本节课主要讲解了 Spring Boot 中如何在业务代码中读取相关配置,包括单一配置和多个配置项,在微服务中,这种情况非常常见,往往会有很多其他微服务需要调用,所以封装一个配置类来接收这些配置是个很好的处理方式。除此之外,例如数据库相关的连接参数等等,也可以放到一个配置类中,其他遇到类似的场景,都可以这么处理。最后介绍了开发环境和生产环境配置的快速切换方式,省去了项目部署时,诸多配置信息的修改。
|
1月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
87 0
|
18天前
|
XML Java 数据库连接
Spring Boot集成MyBatis
主要系统的讲解了 Spring Boot 集成 MyBatis 的过程,分为基于 xml 形式和基于注解的形式来讲解,通过实际配置手把手讲解了 Spring Boot 中 MyBatis 的使用方式,并针对注解方式,讲解了常见的问题已经解决方式,有很强的实战意义。在实际项目中,建议根据实际情况来确定使用哪种方式,一般 xml 和注解都在用。
|
22天前
|
Java Spring 容器
Spring Boot 启动源码解析结合Spring Bean生命周期分析
Spring Boot 启动源码解析结合Spring Bean生命周期分析
59 11