这可能是Spring Boot Starter 讲的最清楚的一次了

news2025/7/26 7:55:36

前面我们简单介绍了如何使用消息中间件Apache Pulsar,但是在项目中那样使用,显然是不太好的,不管从易用性和扩展性来看,都是远远不够, 为了和springboot项目集成,写一个pulsar-spring-boot-starter是非常有必要的,在此之前,我们先看看一个starter需要些什么。

Spring Boot Starter

spring-boot的强大之处在于其提供的大量starter组件,基本涵盖了我们开发中的各个技术领域,比如数据库访问有jdbc、jpa,缓存有redis,全文检索有elasticsearch,消息队列有amqp、kafka等等。

在项目中你只需要按需引入相应的依赖 spring-boot-starter-xxx ,然后只需要替换对应的配置参数即可,就能快速使用对应的功能,不得不说简直是为开发者插上了翅膀。

命名风格

对于starter模块如何命名,spring官方是这样建议:

  • Spring官方命名格式为:spring-boot-starter-{name}

  • 非Spring官方建议命名格式:{name}-spring-boot-starter

准备工作

如果你之前有看过spring官方starter组件,你会发现主要是基于AutoConfigure及@Enable来实现的。

  • 其中AutoConfigure也就是我们常说的自动装配,在spring-boot-autoconfigure包中的目录/METE-INF/spring.factories对应文件中,你可以看到这样的配置:

当启动Spring Boot项目时这些配置都会被加载(这么多的配置全部加载并处理,难怪启动那么慢)。

在starter中依赖的具体实现包中,一般都会提供一个@Enable注解作为部分扩展功能的开关,我们可以在系统中通过该注解引入按需引入配置

 

AutoConfigure配置的一定会被加载,而@Enable有开发者选择使用使用,当然有些组件是没有AutoConfigure,必须通过@Enable来启用

下面我们先对这块内容做个简单的认识,方便后续在写具体starter时知道怎么写以及为什么那样写。

AutoConfigure

在目录中创建src/main/resources/MATE-INF中创建文件spring.factories,定义SpringBoot应用启动时的需要注册的配置,这个主要是基于SPI机制来实现, 下面是当前spring-boot-autoconfigure中spring.factories文件的部分内容

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
...

配置在这里的带有@Configuration的类(如果没有被Conditional条件过滤掉)都会作为配置将相关Bean注册到Spring容器.

主要实现基于@SpringBootApplication注解上的注解@EnableAutoConfiguration

Enable

以Spring Aop相关的注解@EnableAspectJAutoProxy为例,我们看下 Spring官方是怎么使用@Enable注解来实现配置加载的:

@EnableAspectJAutoProxy

改注解除了一般注解的基础(@Target、@Retention)元素外,还包含了两个配置属性proxyTargetClass、exposeProxy以及一个@Import

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    
 boolean proxyTargetClass() default false;
    
 boolean exposeProxy() default false;

}

@Import

在@Import中我们可以配置需要导入的配置类,有以下几个选择:

  • 直接导入@Configuration标识的类

  • 导入实现了接口ImportBeanDefinitionRegistrar的类,来向容器注册BeanDefinition

  • 导入实现了接口ImportSelector的类(不需要@Configuration)来选择配置

@Import(AspectJAutoProxyRegistrar.class)

ImportBeanDefinitionRegistrar

在上面@EnableAspectJAutoProxy注解上,通过@Import,引入了AspectJAutoProxyRegistrar,而该类又实现了接口ImportBeanDefinitionRegistrar, 该接口能够通过BeanDefinitionRegistry向Spring容器注册我们期望的BeanDefinition,看代码:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
  @Override
  public void registerBeanDefinitions(
          AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

    AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    if (enableAspectJAutoProxy != null) {
      if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
      }
      if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
        AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
      }
    }
  }
}

这里我们可以拿到@EnableAspectJAutoProxy的元数据以及对应的属性配置,这样就可以基于开发者的配置实现不同逻辑

ImportSelector

上面说到了,@Import还可以配置实现了ImportSelector接口的类,进而控制具体需要使用的Configuration,下面是@EnableAsync中@Import配置的类

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

  private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
          "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
  
  @Override
  @Nullable
  public String[] selectImports(AdviceMode adviceMode) {
    switch (adviceMode) {
      case PROXY:
        return new String[] {ProxyAsyncConfiguration.class.getName()};
      case ASPECTJ:
        return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
      default:
        return null;
    }
  }
}

ImportAware

同样和@Import配合使用,针对基于ImportSelector选择的Configuration,只要实现了ImportAware接口,就可以拿到@Import对应@Enable注解的元数据

@Configuration
public abstract class AbstractAsyncConfiguration implements ImportAware {
    
  @Override
  public void setImportMetadata(AnnotationMetadata importMetadata) {
    this.enableAsync = AnnotationAttributes.fromMap(
            importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
    if (this.enableAsync == null) {
      throw new IllegalArgumentException(
              "@EnableAsync is not present on importing class " + importMetadata.getClassName());
    }
  }
}

上面主要根据Spring源代码中的例子,了解@Enable、@Import、ImportBeanDefinitionRegistrar、ImportSelector、ImportAware如何搭配使用, 从而实现Spring的动态配置,用一张关系图表示:

relation

其他扩展

spring-boot-configuration-processor

我们知道SpringBoot的配置我们都会写在application.yml(.properties)文件中,为了简化配置工作,如果能有智能提示就好了。这不,别人也想到了。只用这样做:

  1. 现在只需要在项目中引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
  1. 定义一个Properties文件

@Data
@ConfigurationProperties(prefix = "myProp")
public class MyProperties {
  private Boolean enable;
  private String name;
}
  1. 在Configuration中导入

@Configuration
@EnableConfigurationProperties({MyProperties.class})
public class WebApiAutoConfiguration {
    
}
  1. 打包

mvn clean install
  1. 生产metadata.json 可以看到,在jar中的/META-INF目录下多了一个spring-configuration-metadata.json文件

@Conditional

实现spring bean的可插拔,我们可以基于属性、配置、类或者Bean来控制配置(@Configuration)是否生效,常见的有下面的这些:

  • ConditionalOnBean 容器存在Bean时配置有效

  • ConditionalOnClass classpath中有指定class时配置有效

  • ConditionalOnMissingBean 容器不存在Bean时配置有效

  • ConditionalOnMissingClass classpath中没有指定class时配置有效

  • ConditionalOnProperty 属性配置对应值成立时配置有效

AutoConfigure和@Enable

AutoConfigure是在spring.factories中配置了就会加载,但是可以通过@Conditional让配置中的Bean不生效;@Enable需要显示地使用才能有效,且先于AutoConfigure生效,从而可以配合@Conditional来阻断AutoConfigure的配置

结束语

关于Spring框架的学习后面会慢慢增多,我们会从原理到实践来介绍其功能,如果你有感兴趣的技术点或者开发中的问题,可以通过留言进行交流分享。

由于Spring官方文档对框架的介绍可以说是编程届最为详尽的,我们可以通过阅读其文档解决大部分开发中遇到的相关问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/368331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux核心技能:2023主流监控Prometheus详解,附官方可复制中文文档教程

Prometheus既是一个时序数据库&#xff0c;又是一个监控系统&#xff0c;更是一套完备的监控生态解决方案。作为时序数据库&#xff0c;目前Prometheus已超越了老牌的时序数据库OpenTSDB、Graphite、RRDtool、KairosDB等&#xff0c;如图所示。 &#xff08;来源网络&#xff0…

QT+OpenGL鼠标操作和模型控制

文章目录QTOpenGL鼠标操作和模型控制鼠标拾取理论有点小复杂从鼠标计算射线第 0 步&#xff1a;2D 视口坐标第 1 步&#xff1a;3d归一化设备坐标第 2 步&#xff1a;4d齐次剪辑坐标第 3 步&#xff1a;4d眼(相机)坐标第 4 步&#xff1a;4d 世界坐标代码展示模型控制多模型加载…

自动执行自动化测试用例

phpunit 接口自动化测试系列 所有自动化测试用例最终的目的都是一样的&#xff0c;实现无人值守的自动化运行。而目前最常用的就是Jenkins来实现这个功能&#xff0c;在前面的WebdriverPython页面自动化的教程中我们已经详细讲解了如何将自动化测试用例接入到Jenkins中。本章我…

RK系列(RK3568) i2s 音频输入 麦克风驱动

平台&#xff1a;Android12SOC&#xff1a;RK3568外围芯片&#xff1a;XS9922i2s简介&#xff1a;从上图看I2s主要的线有&#xff1a;SDO SCLK LRCK MCLK I2S协议只定义三根信号线&#xff1a;串行时钟信号SCLK(BCLK)、数据信号SD和左右声道选择信号WS。&#xff08;1&#xff…

QT入门Containers之QStackedWidget

目录 一、QStackedWidget界面相关 1、布局介绍 2、插入界面 3、插入类界面 二、Demo展示 此文为作者原创&#xff0c;创作不易&#xff0c;转载请标明出处&#xff01; 一、QStackedWidget界面相关 1、布局介绍 QStackedWidget这个控件在界面布局时&#xff0c;使用还…

JVM整体分析篇

这里写目录标题JVM的组成部分1.类装载子系统1.1一个类加载到JVM的过程1.2类加载机制1.3为什么设计双亲委派机制1.4怎么打破双亲委派机制2.运行时数据区2.1线程私有及共享2.2JVM内存区结构2.3JVM参数设置经验3.Java对象的生命周期3.1.对象的创建3.2.对象大小的计算&#xff08;6…

六、程序计数器(PC寄存器)

JVM中的程序计数寄存器&#xff08;Program Counter Register&#xff09;中&#xff0c;Register 的命名源于CPU的寄存器&#xff0c;寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。 这里&#xff0c;并非是广义上所指的物理寄存器&#xff0c;或许将其…

Python中实现将内容进行base64编码与解码

一、需求说明需要使用Python实现将内容转为base64编码&#xff0c;解码&#xff0c;方便后续的数据操作。二、base64简介Base64是一种二进制到文本的编码方式【是一种基于 64 个可打印字符来表示二进制数据的表示方法&#xff08;由于 2^664&#xff0c;所以每 6 个比特为一个单…

PHP/7.2.11 缺少 apache2/logs/httpd.pid 文件

启动服务时&#xff1a;systemctl restart httpd.service&#xff0c;报错&#xff1a;● httpd.service - httpd serviceLoaded: loaded (/etc/systemd/system/httpd.service; enabled; vendor preset: disabled)Active: failed (Result: exit-code) since 五 2023-02-24 16:1…

Matlab进阶绘图第2期—线型热图

线型热图由共享X轴的多条渐变直线组成&#xff0c;其颜色表示某一特征值。 与传统热图相比&#xff0c;线型热图适应于X轴数据远多于Y轴&#xff08;条数&#xff09;的情况&#xff0c;可以很好地对不同组数据间的分布情况进行比较&#xff0c;也因此可以在一些期刊中看到它的…

IM即时通讯架构技术:可靠性、有序性、弱网优化等

消息的可靠性是IM系统的典型技术指标&#xff0c;对于用户来说&#xff0c;消息能不能被可靠送达&#xff08;不丢消息&#xff09;&#xff0c;是使用这套IM的信任前提。 换句话说&#xff0c;如果这套IM系统不能保证不丢消息&#xff0c;那相当于发送的每一条消息都有被丢失的…

Unity 对接 ML-Agents 初探

一、ML-Agents 是什么 The Unity Machine Learning Agents Toolkit (ML-Agents) is an open-source project that enables games and simulations to serve as environments for training intelligent agents. We provide implementations (based on PyTorch) of state-of-the…

为什么很多人转行IT考虑后端开发Java?

顺应互联网时代发展的选择 在计算机广泛运用于社会的各个角落的今天&#xff0c;选择学习一门计算机语言真的很不错&#xff0c;它会让你的生活从此与众不同。软件渗透到组织的运营和管理的后台之中&#xff0c;形成了组织运营支撑平台。这种形态是传统软件的重要应用场景。在…

matlab simulink Buck三电平dcdc变换器

1、内容简介略653-可以交流、咨询、答疑2、内容说明三电平dc/dc变换器的发展是建立在三电平逆变器的基础上的&#xff0c;由于在三电平dc/dc变换器中每个开关管的电压应力是输入直流电压的一半&#xff0c;具有降低开关管电压应力、减小输入输出滤波器大小、减小储能电感和电容…

【Linux应用】进程间通信消息队列

1.前言 进程间通信简称IPC&#xff08;Inter process communication&#xff09;&#xff0c;进程间通信就是在不同进程之间传播或交换信息。 消息队列是进程通信的一种方式&#xff0c;本质是一个存储消息的链表&#xff0c;这些消息具有特定的格式及特定优先级。消息队列是…

新建一个虚拟环境来管理自己的pytorch环境

python只是一个编程语言&#xff0c;在开发具体软件时&#xff0c;可能还需要使用到各种的包&#xff0c;比如著名的 numpy&#xff0c;torch 等等。如果我们自己来管理则显得非常麻烦&#xff0c;于是便有了Anaconda这样一个类似容器的东西&#xff0c;它封装了python各种各样…

Spring Cloud入门篇 Hello World | Spring Cloud 1

一、专栏说明 Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如:服务发现/注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。 本文主要介绍Spring C…

功能测试三年,是应该改变了

前言 测试行业3年多经验&#xff0c;学历大专自考本科&#xff0c;主要测试方向web&#xff0c;PC端&#xff0c;wap站&#xff0c;小程序公众号都测试过&#xff0c;app也测过一些&#xff0c;C端B端都有&#xff0c;除功能外&#xff0c;接口性能也有涉猎&#xff0c;但是不…

JavaScript 两种方案打开文件对话框

JavaScript 两种方案打开文件对话框 文章目录JavaScript 两种方案打开文件对话框一、文件对话框二、传统方案表单元素&#x1f308;三、文件系统访问API&#x1f4a6;四、更进一步使用六、代码仓库&#x1f310;七、参考资料&#x1f498;七、推荐博文&#x1f357;一、文件对话…

ZYNQ双核处理器独立运行AMP

一、简介多核处理器从多核的结构上是否一致&#xff0c;分为两种基本架构&#xff1a;同构多核架构和异构多核架构。同构多核处理器是指系统中的处理器在结构上是相同的&#xff1b;而异构处理器是指系统中的处理器在结构上是不同的&#xff0c;这些处理器可以是通用处理器&…