配置类需要标注@Configuration却不知原因?那这次就不能给你涨薪喽(中)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 配置类需要标注@Configuration却不知原因?那这次就不能给你涨薪喽(中)
ConfigurationClassParser:
  @Nullable
  protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
    ... // 先解析nested内部类(内部类会存在@Bean方法嘛~)
    ... // 解析@PropertySource资源,加入到environment环境
    ... // 解析@ComponentScan注解,把组件扫描进来
    scannedBeanDefinitions = ComponentScanAnnotationParser.parse(componentScan, ...);
      // 把扫描到的Bean定义信息依旧需要一个个的判断,是否是配置类 
      // 若是配置类,就继续当作一个@Configuration配置类来解析parse() 递归嘛
      for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
        ...
        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
          parse(bdCand.getBeanClassName(), holder.getBeanName());
        }
      }
    ... // 解析@Import注解
    ... // 解析@ImportResource注解
    ... // 解析当前配置里配置的@Bean方法
    ... // 解析接口默认方法(因为配置类可能实现接口,然后接口默认方法可能标注有@Bean )
    ... // 处理父类(递归,直到父类为java.打头的为止)
  }


这个方法是Spring对配置类解析的最核心步骤,通过它顺带也能够解答你的疑惑了吧:为何你仅需在类上标注一个@Configuration注解即可让它成为一个配置类?因为被Scan扫描进去了嘛~


通过以上两个使用处的分析和对比,对于@Configuration配置类的理解,你至少应该掌握了如下讯息:


@Configuration配置类肯定是个组件,存在于IoC容器里

@Configuration配置类是有主次之分的,主配置类是驱动整个程序的入口,可以是一个,也可以是多个(若存在多个,支持使用@Order排序)

我们平时一般只书写次配置类(而且一般写多个),它一般是借助主配置类的@ComponentScan能力完成加载进而解析的(当然也可能是@Import、又或是被其它次配置类驱动的)

配置类可以存在嵌套(如内部类),继承,实现接口等特性

聊完了最为重要的checkConfigurationClassCandidate()方法,当然还有必要看看ConfigurationClassUtils的另一个工具方法isConfigurationCandidate()。


isConfigurationCandidate()

它是一个public static工具方法,通过给定的注解元数据信息来判断它是否是一个Configuration。


ConfigurationClassUtils:
  static {
    candidateIndicators.add(Component.class.getName());
    candidateIndicators.add(ComponentScan.class.getName());
    candidateIndicators.add(Import.class.getName());
    candidateIndicators.add(ImportResource.class.getName());
  }
  public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
    // 不考虑接口 or 注解 说明:注解的话也是一种“特殊”的接口哦
    if (metadata.isInterface()) {
      return false;
    }
    // 只要该类上标注有以上4个注解任意一个,都算配置类
    for (String indicator : candidateIndicators) {
      if (metadata.isAnnotated(indicator)) {
        return true;
      }
    }
    // 若一个注解都没标注,那就看有木有@Bean方法 若有那也算配置类
    return metadata.hasAnnotatedMethods(Bean.class.getName());
  }


步骤总结:


  1. 若是接口类型(含注解类型),直接不予考虑,返回false。否则继续判断
  2. 若此类上标注有@Component、@ComponentScan、@Import、@ImportResource任意一个注解,就判断成功返回true。否则继续判断
  3. 到此步,就说明此类上没有标注任何注解。若存在@Bean方法,返回true,否则返回false。


需要特别特别特别注意的是:此方法它的并不考虑@Configuration注解,是“轻量级”判断,这是它和checkConfigurationClassCandidate()方法的最主要区别。当然,后者依赖于前者,依赖它来根据注解元数据判断是否是Lite模式的配置。

Spring 5.2.0版本变化说明


因为本文的讲解和代码均是基于Spring 5.2.2.RELEASE的,而并不是所有小伙伴都会用到这么新的版本。关于此部分的实现,以Spring 5.2.0版本为分界线实现上有些许差异,所以在此处做出说明。



相关文章
|
8月前
|
前端开发 Java 测试技术
JavaSE碎碎念:记录一次异常测试和一些个人的浅显理解
JavaSE碎碎念:记录一次异常测试和一些个人的浅显理解
|
5月前
|
前端开发 Java 应用服务中间件
一文讲明SpringMVC 【爆肝整理一万五千字】
文章提供了一份全面的SpringMVC教程,涵盖了SpringMVC的简介、创建实例、注解、获取请求参数的不同方式、域对象共享数据、视图渲染、RESTful风格、拦截器使用、异常处理以及文件上传下载等内容,并包含了相应的代码示例和测试结果。
一文讲明SpringMVC 【爆肝整理一万五千字】
|
人工智能 自然语言处理 算法
赶紧学大模型!再不学连对象都找不到了。。。
这次云栖大会的几个笑点之一了,我认为这也能带来一些思考,根据量子位的调研看目前AI大模型工程师的缺口确实很大,这也很可能是计算机行业的下一个风口了。
|
前端开发 Java 编译器
Java的第十六篇文章——枚举、反射和注解(后期再学一遍)
Java的第十六篇文章——枚举、反射和注解(后期再学一遍)
|
安全 Java 程序员
SCPPO(二十二):读取配置文件---程序猿必不可少的技能
SCPPO(二十二):读取配置文件---程序猿必不可少的技能
111 0
|
Java Spring 容器
面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!
面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!
142 0
面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!
|
Java 数据库连接 mybatis
不仔细听课找错找到哭,解决could not find “mybatis.xml“
不仔细听课找错找到哭,解决could not find “mybatis.xml“
不仔细听课找错找到哭,解决could not  find “mybatis.xml“
|
Java Spring 容器
配置类需要标注@Configuration却不知原因?那这次就不能给你涨薪喽(上)
配置类需要标注@Configuration却不知原因?那这次就不能给你涨薪喽(上)
配置类需要标注@Configuration却不知原因?那这次就不能给你涨薪喽(上)
|
存储 Java 程序员
你自我介绍说很懂Spring配置类,那你怎么解释这个现象?(上)
你自我介绍说很懂Spring配置类,那你怎么解释这个现象?(上)
你自我介绍说很懂Spring配置类,那你怎么解释这个现象?(上)
|
设计模式 Java API
你自我介绍说很懂Spring配置类,那你怎么解释这个现象?(中)
你自我介绍说很懂Spring配置类,那你怎么解释这个现象?(中)
你自我介绍说很懂Spring配置类,那你怎么解释这个现象?(中)