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】(中)
|
10天前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
105 17
Spring Boot 两种部署到服务器的方式
|
10天前
|
Dart 前端开发 JavaScript
springboot自动配置原理
Spring Boot 自动配置原理:通过 `@EnableAutoConfiguration` 开启自动配置,扫描 `META-INF/spring.factories` 下的配置类,省去手动编写配置文件。使用 `@ConditionalXXX` 注解判断配置类是否生效,导入对应的 starter 后自动配置生效。通过 `@EnableConfigurationProperties` 加载配置属性,默认值与配置文件中的值结合使用。总结来说,Spring Boot 通过这些机制简化了开发配置流程,提升了开发效率。
45 17
springboot自动配置原理
|
15天前
|
XML JavaScript Java
SpringBoot集成Shiro权限+Jwt认证
本文主要描述如何快速基于SpringBoot 2.5.X版本集成Shiro+JWT框架,让大家快速实现无状态登陆和接口权限认证主体框架,具体业务细节未实现,大家按照实际项目补充。
62 11
|
17天前
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
195 12