SpringBoot自定义Starter

157 阅读5分钟

前言: 在使用Java开发时,我们都必不可免的会使用到Spring这个框架,但是如果一步一步配置来使用类似SSM的开发方式来使用Spring框架的话,我想对许多人来说都是很痛苦的;我们都知道在使用SSM框架时,我们不得不配置一系列的XML文件,非常繁琐且易出错;因此,Spring家族有推出了SpringBoot框架来简化我们的开发,使我们不用过多关注配置而将精力花在业务实现上;而SpringBoot正是通过各种Starter来帮助我们引入对应的开发场景,那我们就来学习如何实现我们自定义的《Starter》

比起传统Spring项目的一大堆配置,Spring Boot更简洁、灵活,提供了一系列 starters 简化开发, 开发人员只需要添加需要的starterSpring Boot可以自动进行配置 ,但实际开发中我们需要开发自己的starter,来简化项目开发配置。开发自定义starter 首先就要了解自动配置的一些知识。

常用条件注解

Class 条件注解

  • @ConditionalOnClass 只有当指定的类在类路径相匹配
  • @ConditionalOnMissingClass 只有当指定的类不在类路径相匹配

Bean 条件注解

  • @ConditionalOnBean 当需要的Bean存在时,配置才会生效
  • @ConditionalOnMissingBean 当需要的Bean不存在时,配置才会生效

Property 条件注解

@ConditionalOnProperty 基于Spring的环境属性配置包括在内。使用prefixname属性来指定应检查的属性。默认情况下,匹配任何存在且不等于false的属性。您还可以使用havingValue和matchIfMissing属性创建更高级的检查。

Resource 条件注解

@ConditionalOnResource 允许仅在存在特定资源时才包含配置。可以使用常见的Spring约定来指定资源。

Web 应用条件注解

  • @ConditionalOnWebApplication 匹配当应用程序是一个Web应用程序。 默认情况下,所有的Web应用将匹配,但它可以通过type()属性缩小范围。
  • @ConditionalOnNotWebApplication 只有当应用程序上下文不是一个Web应用程序才匹配

SpEL 表达式条件注解

@ConditionalOnExpression 允许根据SpEL表达式的结果包含配置

除了上述所说的比较常见的,SpringBoot 还提供了一些别的条件注解,有兴趣大家可直接看源码

定位自动配置

  Spring Boot在启动时检查发布的jar中是否存在META-INF/spring.factories文件。该文件应在EnableAutoConfiguration键下列出的配置类,Spring Boot启动时扫描并进行自动配置,如以下示例所示:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pingfangushi.learning.ExampleAutoConfigure

如果需要按特定顺序应用配置,则可以使用@AutoConfigureAfter@AutoConfigureBefore注释。例如,如果您提供特定于Web的配置,则可能需要在应用类WebMvcAutoConfiguration之后,则应该使用@AutoConfigureAfter(value = WebMvcAutoConfiguration.class)进行标注。

如果想设置自动配置类加载顺序,可使用@AutoConfigureOrder进行处理,此注解只在外部jar中有效,当前项目内无效。

1. 创建SpringBoot项目

image-20230216221539368

image-20230216221620934

点击Finish,然后等待项目构建完成

image-20230216222106289

项目构建完之后,打开pom.xml文件修SpringBoot版本为指定版本号

image-20230220214514569

加入如下依赖:

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--将被@ConfigurationProperties注解的类的属性注入到元数据-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
            <scope>provided</scope>
        </dependency>

元数据配置

元数据表达数据的数据叫做元数据;相应的我们有元注解表达注解的注解叫做元注解;即,表达XX的XX叫做元XX

在使用官方starter的时候,我们可以发现IDE可以进行提示,原因是我们自己封装的starter如何实现呢?

image-20230220225742732转存失败,建议直接上传图片文件

  需要在pom文件中添加 spring-boot-configuration-processor 依赖,刚才我们已经在创建项目的时候添加过了,讲一下原理,Spring Boot使用一个注释处理器来收集元数据文件(META-INF/spring-autoconfigure-metadata.properties)中自动配置的条件。如果该文件存在,它将用于急切地筛选不匹配的自动配置,这将提高启动时间。

简单说就是,spring-boot-configuration-processor依赖会将我们@ConfigurationProperties注解的类的属性的注视收集整理为META-INF/spring-autoconfigure-metadata.properties元数据文件,用于我们在配置对应字段的提示说明;当然我们也可以自己手动编写META-INF/spring-autoconfigure-metadata.json文件配置相应字段的元数据,如下:详细的语法可参考这里

image-20230220230547380

2. 编写Starter项目工程文件

该篇文章示例主要是展示starter项目一般如何编写,所以旨在示例;麻雀虽小,五脏俱全;下面我们一起来看看如何编写我们的starter

MirUtilsProperties 自动注入application.yamlapplication.properties中对应的配置

@Data
@ConfigurationProperties(MirUtilsProperties.PREFIX)
public class MirUtilsProperties {
    public static final String PREFIX = "mir-utils";

    /**
     * 工具功能
     */
    private String function;

    /**
     * 工具版本
     */
    private String version;

}

MirUtilsAutoConfigure自动配置类

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({MirUtilsProperties.class})
@Slf4j
public class MirUtilsAutoConfigure {

    private final MirUtilsProperties mirUtilsProperties;

    public MirUtilsAutoConfigure(MirUtilsProperties mirUtilsProperties) {
        this.mirUtilsProperties = mirUtilsProperties;
    }

    @Bean
    // @ConditionalOnMissingBean 没有注明是何种class时 默认其注解在方法上的返回值类型
    @ConditionalOnMissingBean
    public MirUtilsService defaultMirUtilsService() {
        log.info("register DefaultMirUtilsService to spring bean......");
        return new DefaultMirUtilsService(mirUtilsProperties);
    }
}

MirUtilsService接口

public interface MirUtilsService {

    /**
     * 获取工具基础信息
     * @return
     */
    String getMirUtilsInfo();
}

DefaultMirUtilsService接口默认实现类

public class DefaultMirUtilsService implements MirUtilsService {

    private MirUtilsProperties mirUtilsProperties;

    public DefaultMirUtilsService(MirUtilsProperties mirUtilsProperties) {
        this.mirUtilsProperties = mirUtilsProperties;
    }

    @Override
    public String getMirUtilsInfo() {
        return mirUtilsProperties.getFunction() + ":" + mirUtilsProperties.getVersion();
    }
}

starter项目中只要以上4个文件即可,不需要启动类文件;因为starter项目不会单独启动,一般都是被其他项目依赖来使用,因此不需要启动类。

3. 配置自动配置

resources文件目录下创建META-INF/spring.factories文件,并写入如下内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  mir.github.mirutils.MirUtilsAutoConfigure [自动配置类的全路径]

image-20230220222926297