Starter是SpringBoot中一个非常重要的概念,它为我们带来了众多的自动化配置,有了这些自动化配置,我们可以很方便的搭建一个生产级的开发环境。Starter其实也是Spring+SpringMVC中的基础知识点实现的,其核心就是条件注解@Conditional,即当classpath下存在某一个Class时,某个配置才会生效。我们也可以自己写一个自己的Starter。

1、定义

所谓的Starter,其实就是一个普通的Maven项目,因此我们自定义Starter,首先需要创建一个普通的Maven项目,创建完成之后,添加Starter的自动化配置类即可,如下:

<!--加入依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
      <version>2.1.6.RELEASE</version>
    </dependency>

配置完成之后,我们首先创建一个HelloProperties类,用来接收application.properties中注入的值:

package com.cs;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "cs")
public class HelloProperties {
    private static final String DEFAULT_NAME = "测试";
    private static final String DEFAULT_MSG = "测试成功";
    private String name = DEFAULT_NAME;
    private String msg = DEFAULT_MSG;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

这个配置类是将application.properties中配置的属性值直接注入到这个实例中,@ConfigurationProperties是类型安全的属性注入,即将application.properties文件中前缀为cs的属性注入到这个类对应的属性上,最后使用该stater的时候,application.properties中的配置如下所示:

cs.name=张三
cs.msg=我成功了

配置完成HelleoProperties之后,接下来我们来定义一个HelloService,然后定义一个简单的sayHello方法:

package com.cs;


public class HelloService {
    private String name;
    private String msg;

    public String sayHello(){
        return name + " say " + msg +"!";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

接下来,就是自动配置类的定义:

package com.cs;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 自动配置类定义
 */
@Configuration
@EnableConfigurationProperties(HelloProperties.class)
@ConditionalOnClass(HelloService.class)
public class HelloServiceAutoConfiguration {

    @Autowired
    HelloProperties helloProperties;

    @Bean
    HelloService helloService(){
        HelloService helloService = new HelloService();
        helloService.setName(helloProperties.getName());
        helloService.setMsg(helloProperties.getMsg());
        return helloService;
    }
}

关于这一段自动配置,解释如下:

  1. 首先,@Configuration注解表名这是一个配置类。
  2. @EnableAutoConfigurationProperties注解是使我们之前配置的@ConfiguarationProperties生效,让配置的属性成功进入Bean中。
  3. @ConditionalOnClass表示当项目当前classpath下存在HelloService时,后面的配置才生效。
  4. 自动配置类首先注入HelloProperties,这个实例中含有我们在application.properties中配置的相关数据。
  5. 提供一个HelloService实例,将HelloProperties中的值注入进去。

做完这一步之后,我们的自动化配置类就算完成了,接下来还需要一个spring.factories文件,那么这个文件是干嘛的呢?大家知道我们的SpringBoot项目的启动类都有一个@SpringBootApplication注解,这个注解的定义如下:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
......

从这里我们可以知道,这是一个组合注解,其中的一个组合项就是@EnableAutoConfiguration,这个注解是干嘛的呢?

@EnableAutoConfiguration表示启用Spring应用程序上下文的自动配置,该注解会自动导入一个名为AutoConfigurationImportSelector的类,而这个类会去读取一个名为spring.facotries的文件,spring.factories中则定义需要加载的自动化配置类,当我们打开任意一个框架的Starter,都能看到他有一个spring.factories文件,例如MyBatis的Starter如下:

springboot的startet如何编写和引用 springboot中starter_上传


我们自定义Starter也需要这样一个文件,我们首先在maven项目的resources目录下创建一个名为META-INF的文件夹,然后在文件夹中创建一个spring.factories的文件,如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.cs.HelloServiceAutoConfiguration

springboot的startet如何编写和引用 springboot中starter_自定义_02


这样,我们的自动化配置类就算完成了。

2、本地安装

如果在公司里,我们需要将刚刚写好的自动化配置类打包,然后上传到Maven私服上,供其他同事下载使用,这里我们就不上传私服了,直接将这个自动化配置类安装到本地仓库,然后再其他项目中使用即可。安装方式很简单,在idea中,点击右面的Maven Project,然后选择Lifecycle中的install,双击即可,如下:

springboot的startet如何编写和引用 springboot中starter_自定义_03


完成之后,这个Starter就安装到我们本地仓库了,当然,我们也可以使用命令去安装。

3、使用Starter

接下来,我们新建一个普通的SpringBoot工程,创建成功后,加入我们自定义的Starter的依赖,如下:

<!--加入自定义的sarter依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

此时,我们引入了上面我们自定义的Starter,也就是说我们项目中现在有一个默认的HelloService实例可以使用,而且关于这个实例的数据,我们还可以在application.properties中进行配置,如下:

cs.name=张三
cs.msg=我成功了

配置完成之后,方便起见,我们可以直接在单元测试方法中注入HelloService实例来使用,代码如下:

package com.cs;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class UseautoconfigurestarterdemoApplicationTests {
    @Autowired
    HelloService helloService;

    @Test
    void contextLoads() {
        System.out.println(helloService.sayHello());
    }

}

执行单元测试,打印日志如下:

springboot的startet如何编写和引用 springboot中starter_自定义_04


如果不配置application.properties,则打印出默认值:

springboot的startet如何编写和引用 springboot中starter_自定义_05

测试代码位置:

本文参考:http://springboot.javaboy.org/2019/0520/springboot-starter