先抛开springboot的autoconfig和starter,只看如果我们想要创建一个自己的starter的情况。

那么,这个starter的作用是什么???

在springboot官网上有一句话:

Auto-configuration can be associated to a “starter” that provides the auto-configuration code as well as the typical libraries that you would use with it. We first cover what you need to know to build your own auto-configuration and then we move on to the ​​typical steps required to create a custom starter​​.

说明,我们自定义的一个starter,在通常情况下,可以包含下面两个模块:

1)我们提供的特定功能的library;

2)导入library的相关配置代码,主要是带有@Configuration注解的java配置类;

这应该是一种通用场景。这样,作为需要导入library的工程,即使用方来说,只需要导入这个starter即可,即包含了相关了jar包,也包含了各种bean的配置。这也是springboot自动配置的理念。

 

springboot中提供的starter可能和上面略微不同(2.1.7版本)。

有一个专门的autoconfig工程,统一管理了springboot中所有的自动配置类。相关的starter只负责导入相应的jar包即可。自动配置类根据@Condition注解结合classpath下的jar包,来决定启动哪些自动配置的功能。

比如说spring-boot-starter-web这个工程,其实是一个空的工程,仅仅包含了一个pom文件,导入了一些web相关的依赖。自动配置类是在spring-boot-autoconfigure工程里。

 

下面写一个简单的starter的例子MyBizStarter。

创建一个普通的maven工程。

pom文件:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.liyao</groupId>
<artifactId>mybiz-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
</project>

有几个点:

1)需要继承springboot的父pom文件,将依赖的版本交给springboot的统一管理;

2)spring-boot-configuration-processor依赖的作用是生成meta-json文件,该文件的作用是给IDE提供元数据,这样我们如果想覆盖一下配置参数,会有对应的提示,idea是支持的;

3)导入spring-boot-autoconfigure依赖,不然编译不过。(其实,pring-boot-autoconfigure的pom里是引入了spring-boot-configuration-processor的依赖的,只不过是optional的,所以需要重新引入);

 

配置属性类:

@ConfigurationProperties(prefix = "mybiz")
public class MyBizProperties {

private static final String DEFAULT_NAME = "ly";
private String name = DEFAULT_NAME;

public String getName() {
return name;
}

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

定义了配置的前缀为“mybiz”,属性这里只有一个name,默认值为“ly”。

 

配置类:

@Configuration
@EnableConfigurationProperties(MyBizProperties.class)
public class EnableMyBizConfiguration {

@Autowired
private MyBizProperties myBizProperties;

@ConditionalOnMissingBean(MyBizService.class)
@Bean
public MyBizService getMyBizService() {
MyBizService myBizService = new MyBizService();
myBizService.setName(myBizProperties.getName());
return myBizService;
}
}

配置了一个bean,bean的属性从之前的属性文件里读取。

 

配置文件:

在resources/META-INF/spring.fatocries:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.liyao.mybiz.EnableMyBizConfiguration

 

service类:

public class MyBizService {

private String name;

public String hello() {
return "hello, " + name;
}

public String getName() {
return name;
}

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

仅仅是但会一个string。

 最后使用mvn clean install,安装到本地maven仓库。

 

然后在另一个springboot项目里导入这个starter依赖:

<dependency>
<groupId>com.liyao</groupId>
<artifactId>mybiz-spring-boot-starter</artifactId>
<version>1.2</version>
</dependency>

在controller使用之前的service:

@RestController
public class MainController {

@Autowired
private MyBizService myBizService;

@RequestMapping("/hello")
public String hello() {
return myBizService.hello();
}
}

使用mvn spring-boot:run启动工程。

默认显示

hello, lz。

覆盖默认值,在resouces/application.properties里覆盖之前的name:

mybiz.name=lzy

重新启动工程,显示:

hello, lzy。

 

另外,在修改application.properties会有提示,是因为之前使用了processor生成了一个json的meta文件,在starter的jar包下:

{
"groups": [
{
"name": "mybiz",
"type": "com.liyao.mybiz.MyBizProperties",
"sourceType": "com.liyao.mybiz.MyBizProperties"
}
],
"properties": [
{
"name": "mybiz.name",
"type": "java.lang.String",
"sourceType": "com.liyao.mybiz.MyBizProperties",
"defaultValue": "ly"
}
],
"hints": []
}