1. 概述

我们在使用SpringBoot做开发的时候经常会使用到starter,starter给我们提供了一些开箱即用的功能,例如我们想使用某个中间件的时候,只需要引入并在配置文件中写一些少量的配置就可以直接使用了,像Redis,Spring Data,mybatis以及RabbitMQ等等。
既然用来这么方便,那在我们做项目的脚手架的时候,通过starter做一些团队都能用上的基础包封装,后续团队开发起来需要使用的时候就方便了。那么本篇就来聊一聊如何的编写一个自定义的starter。

在之前的文章《XXL-JOB的执行器配置》中曾写到了,如果不想在每个使用到定时任务的服务中都去编写一套重复的配置,就可以使用SpringBoot的starter做一下封装,今天就来把这个坑填上。

使用版本为SpringBoot2的最后一个版本,2.7.18

2.自动装配原理及自定义starter编写

下面先简单的聊一下SpringBoot的自动装配原理是怎么回事,熟悉原理之后再自定义一个starer就是水到渠成的事情了。

2.1.简单聊聊SpringBoot的自动装配原理

我们可以知道的是,SpringBoot是通过扫描包获取的Bean定义,再经过实例化与初始化获得最终可以执行任务的bean对象,这种对Bean扫描再初始化的方式,依赖的是对扫描路径的配置(当然,SpringBoot的默认扫描路径就是Application类下的所有子包)。

那么问题来了,我们在使用三方jar包的时候,三方包的包路径与我们项目中的路径并不一致,这时候Spring应该如何扫描到jar包中Bean定义呢?
手动配置三方jar包的依赖路径倒是可以解决这个问题,但是不同的三方包,其包路径也不一样,我们不可能没新增一个新的包,就配置一下路径,这个时候就需要使用的SpringBoot的自动装配机制了


自动装配机制有点类似于SPI的思想,简单的说,就是在需要封装成starter的项目的META-INF加入一个配置文件,这个配置文件里面写了需要扫描的类的全类名,SpringBoot在启动的时候会获取到这个文件,扫描对应的类,并把需要加载的Bean加载到Spring的容器中
配置文件的路径有两种,分别是:

  • META-INF/spring.factories
  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

前者是相对旧一点的版本,并且在SpringBoot3.0后弃用,后者大概是在2.7版本后才新增,并且在3.0的时候正式使用(原因大概使用因为后者支持3.0的新特性,可以在编译时处理注解,性能优于前者)。
在这里插入图片描述
通过上图打开的文件,从左到右的顺序可以找到这行代码,同时也能找到下面的代码。
在这里插入图片描述
也就是说,需要扫描的Bean不管是写在其中的哪一个文件中,都可以被扫描到。

2.2.自定义starter编写

有了上面基础之后,就可以开始编写starter了,对于XXL-JOB执行器的封装,只需要简单的四步就可以了。

  • 创建一个2.7.18版本的SpringBoot项目
  • 将项目中的XXL-JOB执行器配置拷贝过来
  • 编写配置文件
  • 打包供其他项目引用

2.3.1.项目初始化及代码编写

初始化项目的时候需要注意命名规则,一般来说有两种规则:

  • Spring官方的starter:一般是spring-boot-starter-xxx的形式
  • 三方的starter:一般是xxx-spring-boot-starter的形式

可以看到,spring-boot-starter 一个在开头,一个在结尾,我们命名的时候也要注意这个规范,这里命名为my-xxl-job-spring-boot-starter
在这里插入图片描述

项目建好之后,将之前xxl-job文中的配置搬过来,新建两个类:

@ConfigurationProperties(prefix = "xxl.job.executor")
public class XxlJobProperties {

    /**
     * 在业务服务配置文件中配置
     */
    private String appname;

    /**
     * 下面直接写死公司的配置
     */
    private String adminAddresses = "http://ls.xxljob.cn/xxl-job-admin";
    private String accessToken = "default_token";
    private int port = 9999;
    private String logPath = "/data/applogs/xxl-job/jobhandler";
    private int logRetentionDays = 30;

    private String address ;
    private String ip;

	……忽略getter,setter 
}
@Configuration
@EnableConfigurationProperties({XxlJobProperties.class})
public class XxlJobConfig {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "xxl.job.executor", value = "appname")
    public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties xxlJobProperties) {

        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(xxlJobProperties.getAdminAddresses());
        xxlJobSpringExecutor.setAppname(xxlJobProperties.getAppname());
        xxlJobSpringExecutor.setAddress(xxlJobProperties.getAddress());
        xxlJobSpringExecutor.setIp(xxlJobProperties.getIp());
        xxlJobSpringExecutor.setPort(xxlJobProperties.getPort());
        xxlJobSpringExecutor.setAccessToken(xxlJobProperties.getAccessToken());
        xxlJobSpringExecutor.setLogPath(xxlJobProperties.getLogPath());
        xxlJobSpringExecutor.setLogRetentionDays(xxlJobProperties.getLogRetentionDays());

        return xxlJobSpringExecutor;
    }
}

需要说明一下的是,@Conditional是Spring中的一个条件注解,其作用是让Bean在满足一定条件之后才会加载到Spring容器中,下面例举几个常见的注解:

  • @ConditionalOnProperty:根据配置文件中的属性是否存在、是否为某个值来加载 Bean。
    • prefix:配置属性的前缀
    • value:属性名
    • havingValue:当属性值等于指定值时条件成立
    • matchIfMissing:属性缺失时,是否视为满足条件,默认为 false
  • @ConditonalOnMissingBean(xx.class):容器中没有某个bean对象时才执行创建,不指定则默认是当前方法的返回值对应的bean对象。
  • @ConditionalOnBean(xx.class):与上面的相反,容器中有某个bean对象时才创建,用于需要一些依赖关系的时候。
  • @ConditionalOnClass(name = "com.example.SomeClass"):当指定类存在于类路径上时加载 Bean。
  • @ConditionalOnMissingClass("com.example.SomeClass"):当指定类不存在于类路径时加载 Bean。

2.3.2.配置文件编写

因为是2.7.x的版本,可以在resources下创建配置文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,并在配置文件中加入全类名

com.ls.config.XxlJobConfig

要在较低版本中实现自动配置,需要在 META-INF/spring.factories 文件中添加以下内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ls.config.XxlJobConfig

2.3.3.校验结果

配置完了之后的结构如下:
在这里插入图片描述
直接通过install打包后,用其他的SpringBoot引用,加入properties配置:

xxl.job.executor.appname=my-simple-executor

打好断点启动,成功进入断点,表示starter编写成功。
在这里插入图片描述

3.总结

本篇主要是简单介绍了一下SpringBoot的自动装配原理,同时通过XXL-JOB演示了一下如何创建一个自定义的starter,项目开发中可以通过这样的方式来创建一些脚手架工程。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部