SpringBoot如何自定义starter,你觉得有必要吗?

1. 什么是starter

Springboot的出现极大的简化了开发人员的配置,而这之中的一大利器便是springboot的starter,starter是springboot的核心组成部分,为什么说引入如下依赖就满足了日常web开发?

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

而不使用springboot时,需要引入spring-web、spring-webmvc、spring-aop等等。实际上那些必要的依赖在spring-boot-starter-web中已经被引入了,引入这个组名就引入了所有的依赖。

2. 自动配置原理

springboot在启动的时候会加载主配置类,开启了@EnableAutoConfiguration。

@EnableAutoConfiguration的作用:

  • 利用AutoConfigurationImportSelector给容器导入一些组件。
  • 查看selectImports方法的内容,返回一个AutoConfigurationEntry
  • 可以看到SpringFactoriesLoader.loadFactoryNames,继续看又调用了loadSpringFactories方法,获取META-INF/spring.factories资源文件。这个spring.factories文件也是一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔,最后都加入到容器中,用来做自动配置,每一个自动配置类都可以进行自动配置功能使用HttpEncodingAutoConfiguration来解释自动装配原理。根据当前不同的条件判断,决定这个配置类是否生效!

2.1 自动配置生效

每一个XxxxAutoConfiguration自动配置类都是在某些条件之下才会生效的,这些条件的限制在Spring Boot中以注解的形式体现,常见的条件注解有如下几项:

@Conditional扩展注解 作用
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean
@ConditionalOnMissingBean 容器中不存在指定Bean
@ConditionalOnExpression 满足SpEL表达式
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境

自动配置原理总结如下:

	1、Spring Boot启动的时候会通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类进行加载

	2、这些自动配置类都是以AutoConfiguration结尾来命名的,它实际上就是一个JavaConfig形式的Spring容器配置类

	3、自动配置类通过以Properties结尾命名的类中取得在全局配置文件中配置的属性如:server.port,而XxxxProperties类是通过@ConfigurationProperties注解与全局配置文件中对应的属性进行绑定的。

3. 自定义starter

spring-boot有两种starter:

  • 一种是内部已经支持的,其通过@ConditionalOnClass来实决定是否例化(ConditionalOnClass是指当在classpath发现需要的依赖的类时实例化),想要启动这个服务,只要要配置上对应的starter,这个starter就能把所需要的jar给关联上。
  • 一种是第三方的,比如mybatis等。原理是一样的,就是在你已经实现的服务代码之上封装一层配置代码就行。

基于这个机制,我们自己也可以实现一个。自定义starter,我们要做的事情是两个:确定依赖和编写自动配置。我们重点要做的就是编写自动配置,我们之前写过一些自动配置,主要是注解配置的使用,主要的注解有:

  • @Configuration :指定这个类是一个配置类
  • @ConditionalOnXXX :在指定条件成立的情况下自动配置类生效
  • @AutoConfigureAfter:指定自动配置类的顺序
  • @Bean:给容器中添加组件
  • @ConfigurationPropertie:结合相关xxxProperties类来绑定相关的配置
  • @EnableConfigurationProperties:让xxxProperties生效加入到容器中

3.1 命名规范

SpringBoot提供的starter以spring-boot-starter-xxx的方式命名的。官方建议自定义的starter使用xxx-spring-boot-starter命名规则。以区分SpringBoot生态提供的starter。

官方命名空间

  • 前缀:“spring-boot-starter-”
  • 模式:spring-boot-starter-模块名
  • 举例:spring-boot-starter-web、spring-boot-starter-jdbc

自定义命名空间

  • 后缀:“-spring-boot-starter”
  • 模式:模块-spring-boot-starter
  • 举例:druid-spring-boot-starter、mybatis-spring-boot-starter

4. 码农来洞见

Starter可以理解为一个可拔插式的插件,提供一系列便利的依赖描述符,您可以获得所需的所有Spring和相关技术的一站式服务。应用程序只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。

4.1为什么要自定义starter?

在我们的日常开发工作中,经常会有一些独立于业务之外的配置模块,我们经常将其放到一个特定的包下,然后如果另一个工程需要复用这块功能的时候,需要将代码硬拷贝到另一个工程,重新集成一遍,麻烦至极。如果我们将这些可独立于业务代码之外的功能配置模块封装成一个个starter,复用的时候只需要将其在pom中引用依赖即可。

4.2 自定义starter的案例

以下案例由笔者工作中遇到的部分场景

  • 动态数据源。 — fs-dynamic-starter
  • 登录模块(权限)。— fs-auth-client-starter
  • 基于AOP技术实现日志切面。—fs-common-starter

案例地址:https://gitee.com/Manoninsight/fullset/tree/master/fs-starter

这里还有一个小细节,你如果仔细查看我的案例会发下一个问题,就是我自定义的starter里并没有META-INF/spring.factories配置文件,为什么还能生效呢?这是因为我的项目用的统一的包路径:com.fs。spring配置默认会扫描当前的包路径,所以能加载到。但是笔者建议还是加上META-INF/spring.factories配置文件。

猜你喜欢

转载自blog.csdn.net/pangpengshuai/article/details/121097981
今日推荐