SpringBoot源码分析系列之一:配置自动化

简介: 大家都知道SpringBoot简化了Spring开发工作,让开发者不用再去面对繁琐的配置,可以使我们可以迅速上手进行开发,将重点放在业务逻辑的实现上。但也正因为这样,使得开发者容易忽略对于其背后原理的理解。我们可能知道怎么用,但是实际上并不知道SpringBoot如何实现自动配置以及如何通过内置tomcat进行启动等等的原理。为了探究SpringBoot背后的技术原理,特地将学习的过程记录下来形成一个文章系列,另外希望对这方面有相同困惑的同学有所裨益。自动配置介绍Kafka自动配置源码分析总结

引言

大家都知道SpringBoot简化了Spring开发工作,让开发者不用再去面对繁琐的配置,可以使我们可以迅速上手进行开发,将重点放在业务逻辑的实现上。但也正因为这样,使得开发者容易忽略对于其背后原理的理解。我们可能知道怎么用,但是实际上并不知道SpringBoot如何实现自动配置以及如何通过内置tomcat进行启动等等的原理。为了探究SpringBoot背后的技术原理,特地将学习的过程记录下来形成一个文章系列,另外希望对这方面有相同困惑的同学有所裨益。

自动配置介绍

Kafka自动配置源码分析

总结


一、自动配置介绍

我们都知道,在没有SpringBoot之前,利用Spring进行开发的时候,研发需要花费大量精力去定义模板化的各类配置文件。Spring最初使用Bean Factory以及动态代理实现各模块之间的解耦,它通过配置文件将bean扫描到Spring容器中。而SpringBoot将这种xml解析配置的过程,通过注解自动配置的方式来进行替换,它根据定义在classpath下的类,自动生成对应的bean,同时将其加载到Spring的context中。SpringBoot通过条件化配置来启动某个能力项。


在SpringBoot启动类WebApplication中,可以看到很多个注解。我们知道SpringBoot项目是高度依赖注解的,它可以在main函数中启动整个应用。

@SpringBootApplication(scanBasePackages = {"com.test"})
@MapperScan("com.test.module.mapper")
@ImportResource(locations = {"classpath:springMVC-servlet.xml"})
@ServletComponentScan
public class WebApplication extends SpringBootServletInitializer{
  static Logger logger = LoggerFactory.getLogger(WebApplication.class);
  public static void main(String[] args) {
      SpringApplication.run(WebApplication.class, args);
  }
}

以上代码中,@SpringBootApplication是SpringBoot的核心注解,它是一系列注解的集合。它对应的源码如下所示。在这些注解当中@EnableAutoConfiguration即为当前的项目提供自动配置功能,它也是一系列注解的集合。该注解可以让Spring Boot根据类路径中的jar包依赖为当前项目进行自动配置。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
  @AliasFor(annotation = EnableAutoConfiguration.class)
  Class<?>[] exclude() default {};
  @AliasFor(annotation = EnableAutoConfiguration.class)
  String[] excludeName() default {};
  @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
  String[] scanBasePackages() default {};
  @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
  Class<?>[] scanBasePackageClasses() default {};
}

通过注解的方式实现配置的自动化,主要在spring-boot-autoconfigure-1.4.3.RELEASE-sources.jar这个jar包中提供了对于SpringBoot自动化配置的支持。这个jar包中包含了如下包,篇幅有限只列出了部分包。

1.png

在这个jar包中的META-INF文件夹中,可以看到spring.factories文件

image.png

在spring.factories文件中我们看到了一些初始化的类、监听器以及构建类等等。

image.png


我们具体看一下@EnableAutoConfiguration这个注解里面的内容。Spring中有很多@Enable-*开头的注解,类似@EnableScheduling以及@EnableCaching等等,这类注解即为该修饰的类赋予某项能力,在每个该类注解中都会通过@Import注解来导入实现对应功能的类。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
  String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
  /**
   * Exclude specific auto-configuration classes such that they will never be applied.
   * @return the classes to exclude
   */
  Class<?>[] exclude() default {};
  /**
   * Exclude specific auto-configuration class names such that they will never be
   * applied.
   * @return the class names to exclude
   * @since 1.3.0
   */
  String[] excludeName() default {};
}

在该注解中引入了EnableAutoConfigurationImportSelector这个类,按照这个类的字面理解为自动配置导入选择器,它实现了以下几个接口。

public class AutoConfigurationImportSelector
    implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
    BeanFactoryAware, EnvironmentAware, Ordered{
......
    }

在这个类中,使用SpringFactoriesLoader.loadFactoryNames方法来扫描具有META-INF/spring.factories文件的jar包,spring-boot-autoconfigure-x.x.x.x.jar里就有一个spring.factories文件,这个文件中声明了有哪些类要自动配置。

  protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
      AnnotationAttributes attributes) {
    //获取  
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
        getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
    Assert.notEmpty(configurations,
        "No auto configuration classes found in META-INF/spring.factories. If you "
            + "are using a custom packaging, make sure that file is correct.");
    return configurations;
  }

二、Kafka自动配置源码分析

下面分析下Kafka自动配置类,贴上其源码,相关源码已经加上注释。

//配置注解
@Configuration
//KafkaTemplate类在classpath目录下存在时,才会去解析KafkaAutoConfiguration自动配置类
@ConditionalOnClass(KafkaTemplate.class)
//自动注入属性,如果在application.properties配置文件中定义,则会将配置文件中key对应的value值注入到KafkaProperties中
@EnableConfigurationProperties(KafkaProperties.class)
//导入KafkaAnnotationDrivenConfiguration
@Import(KafkaAnnotationDrivenConfiguration.class)
public class KafkaAutoConfiguration {
  private final KafkaProperties properties;
  private final RecordMessageConverter messageConverter;
  public KafkaAutoConfiguration(KafkaProperties properties,
      ObjectProvider<RecordMessageConverter> messageConverter) {
    this.properties = properties;
    this.messageConverter = messageConverter.getIfUnique();
  }
  //向Spring容器注入bean
  @Bean
  //在上下文中没有KafkaTemplate时,才会实例化bean
  @ConditionalOnMissingBean(KafkaTemplate.class)
  public KafkaTemplate<?, ?> kafkaTemplate(
      ProducerFactory<Object, Object> kafkaProducerFactory,
      ProducerListener<Object, Object> kafkaProducerListener) {
    KafkaTemplate<Object, Object> kafkaTemplate = new KafkaTemplate<>(
        kafkaProducerFactory);
    if (this.messageConverter != null) {
      kafkaTemplate.setMessageConverter(this.messageConverter);
    }
    kafkaTemplate.setProducerListener(kafkaProducerListener);
    kafkaTemplate.setDefaultTopic(this.properties.getTemplate().getDefaultTopic());
    return kafkaTemplate;
  }
  @Bean
  @ConditionalOnMissingBean(ProducerListener.class)
  public ProducerListener<Object, Object> kafkaProducerListener() {
    return new LoggingProducerListener<>();
  }
  @Bean
  @ConditionalOnMissingBean(ConsumerFactory.class)
  public ConsumerFactory<?, ?> kafkaConsumerFactory() {
    return new DefaultKafkaConsumerFactory<>(
        this.properties.buildConsumerProperties());
  }
  @Bean
  @ConditionalOnMissingBean(ProducerFactory.class)
  public ProducerFactory<?, ?> kafkaProducerFactory() {
    DefaultKafkaProducerFactory<?, ?> factory = new DefaultKafkaProducerFactory<>(
        this.properties.buildProducerProperties());
    String transactionIdPrefix = this.properties.getProducer()
        .getTransactionIdPrefix();
    if (transactionIdPrefix != null) {
      factory.setTransactionIdPrefix(transactionIdPrefix);
    }
    return factory;
  }
  @Bean
  @ConditionalOnProperty(name = "spring.kafka.producer.transaction-id-prefix")
  @ConditionalOnMissingBean
  public KafkaTransactionManager<?, ?> kafkaTransactionManager(
      ProducerFactory<?, ?> producerFactory) {
    return new KafkaTransactionManager<>(producerFactory);
  }
  @Bean
  @ConditionalOnProperty(name = "spring.kafka.jaas.enabled")
  @ConditionalOnMissingBean
  public KafkaJaasLoginModuleInitializer kafkaJaasInitializer() throws IOException {
    KafkaJaasLoginModuleInitializer jaas = new KafkaJaasLoginModuleInitializer();
    Jaas jaasProperties = this.properties.getJaas();
    if (jaasProperties.getControlFlag() != null) {
      jaas.setControlFlag(jaasProperties.getControlFlag());
    }
    if (jaasProperties.getLoginModule() != null) {
      jaas.setLoginModule(jaasProperties.getLoginModule());
    }
    jaas.setOptions(jaasProperties.getOptions());
    return jaas;
  }
  @Bean
  @ConditionalOnMissingBean
  public KafkaAdmin kafkaAdmin() {
    KafkaAdmin kafkaAdmin = new KafkaAdmin(this.properties.buildAdminProperties());
    kafkaAdmin.setFatalIfBrokerNotAvailable(this.properties.getAdmin().isFailFast());
    return kafkaAdmin;
  }
}

三、总结

将SpringBoot自动配置过程用流程图进行表示,更能形象化的理解自动配置的流程。

2.png

相关文章
|
6月前
|
人工智能 Ubuntu 前端开发
Dify部署全栈指南:AI从Ubuntu配置到HTTPS自动化的10倍秘籍
本文档介绍如何部署Dify后端服务及前端界面,涵盖系统环境要求、依赖安装、代码拉取、环境变量配置、服务启动、数据库管理及常见问题解决方案,适用于开发与生产环境部署。
1324 1
|
11月前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
669 7
|
10月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
960 1
|
6月前
|
Java 测试技术 数据安全/隐私保护
通过yaml文件配置自动化测试程序
通过yaml文件可以将自动化测试环境,测试数据和测试行为分开,请看一下案例
208 4
|
11月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
627 70
|
10月前
|
供应链 JavaScript BI
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
773 2
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
|
9月前
|
人工智能 运维 Java
配置优化还靠拍脑袋?试试AI自动化,真香!
配置优化还靠拍脑袋?试试AI自动化,真香!
281 0
|
12月前
|
小程序 Java 关系型数据库
weixin117新闻资讯系统设计+springboot(文档+源码)_kaic
本文介绍了一款基于微信小程序的新闻资讯系统,涵盖其开发全过程。该系统采用Java的SSM框架进行后台管理开发,使用MySQL作为本地数据库,并借助微信开发者工具确保稳定性。管理员可通过个人中心、用户管理等功能模块实现高效管理,而用户则能注册登录并查看新闻与视频内容。系统设计注重可行性分析(技术、经济、操作),强调安全性与数据完整性,界面简洁易用,功能全面,极大提升了信息管理效率及用户体验。关键词包括基于微信小程序的新闻资讯系统、SSM框架和MYSQL数据库。
|
9月前
|
机器学习/深度学习 数据采集 人机交互
springboot+redis互联网医院智能导诊系统源码,基于医疗大模型、知识图谱、人机交互方式实现
智能导诊系统基于医疗大模型、知识图谱与人机交互技术,解决患者“知症不知病”“挂错号”等问题。通过多模态交互(语音、文字、图片等)收集病情信息,结合医学知识图谱和深度推理,实现精准的科室推荐和分级诊疗引导。系统支持基于规则模板和数据模型两种开发原理:前者依赖人工设定症状-科室规则,后者通过机器学习或深度学习分析问诊数据。其特点包括快速病情收集、智能病症关联推理、最佳就医推荐、分级导流以及与院内平台联动,提升患者就诊效率和服务体验。技术架构采用 SpringBoot+Redis+MyBatis Plus+MySQL+RocketMQ,确保高效稳定运行。
662 0
|
小程序 JavaScript Java
基于SpringBoot的智慧停车场微信小程序源码分享
智慧停车场微信小程序主要包含管理端和小程序端。管理端包括停车场管理,公告信息管理,用户信息管理,预定信息管理,用户反馈管理等功能。小程序端包括登录注册,预约停车位,停车导航,停车缴费,用户信息,车辆信息,钱包充值,意见反馈等功能。
643 5
基于SpringBoot的智慧停车场微信小程序源码分享

热门文章

最新文章