曾遇到几位面试者,简历上写着精通Spring Boot,当聊到自动配置及对starter的理解时,却说不出个所以然来。找工作时,简历一定要注重实际,精通这种字眼还是少用,不然面试官对你期望越高,失望也就越大。其实结合前一篇介绍的Spring Boot自动配置,对Spring Boot的Starter实现将很容易理解,不论是使用其官方提供的Starter,还是自定义自己的Starter,都变得很容易。

根据前面介绍,Spring Boot自动配置的实现,主要由如下几部分完成:

  1. @EnableAutoConfiguration注解
  2. SpringApplication类
  3. spring-boot-autoconfigure jar包
  4. spring.factories文件

项目结构

官方提供的starter,大多包含两个jar包: 一个starter——没有任何实现,只用来管理依赖(即实现这个starter的功能需要依赖哪些jar),一个autoconfigure——包含所有具体实现,包括自动配置类,及META-INF/spring.factories文件。本文示例的自定义starter,为了方便,将两者合并写到了一个。

但是在实际项目中,还是建议像官方一样,定义一个spring-boot-dependencies声明所有依赖及其版本,做统一依赖版本管理,一个spring-boot-autoconfigure,实现所有自动配置类及相应的Bean,一个spring-boot-starters,针对每个模块引入必须的jar依赖,方便项目中引入。

官方提供的starter,命名遵循spring-boot-starter-xxx, 自定义starter,命名遵循xxx-spring-boot-starter。

示例的项目结构如下图
starter项目结构

springboot-starter

这里为了简单,将starter与autoconfigure整到一个项目,命名也为了与前面demo项目保持一致,没按规范来。

配置类 MyAutoConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfig {

@Autowired
private MyProperties myProperties;

@Bean
@ConditionalOnProperty(prefix = "my", name = "disable", havingValue = "false")
public MyService myService(){
return new MyService("Hi " + myProperties.getName() + ", welcome to visit " + myProperties.getWebsite());
}
}

该类中通过@EnableConfigurationProperties@Autowired 引入了配置属性Bean MyProperties 以访问用户配置的属性,@Bean注解即向容器中注入方法返回值类型的Bean,这样在容器其它bean中通过@Autowired即可引用访问, @ConditionalOnProperty是条件注解,这里表明当配置属性my.disable=false时才实例化这个MyService bean。

配置属性类 MyProperties

1
2
3
4
5
6
7
@ConfigurationProperties(prefix = "my")
public class MyProperties {
private String name;
private String website;

getter/setter;
}

配置属性类封装了用户在配置文件中定义的属性,该示例中将前缀为my的属性封装起来,访问name,website对应配置属性key就是my.name,my.website。

服务Bean MyService

1
2
3
4
5
6
7
8
9
10
11
public class MyService {
private String hiStr;

public MyService(String hiStr){
this.hiStr = hiStr;
}

public String sayHi(){
return this.hiStr;
}
}

提供服务功能的bean,也即需要实例化注入到Spring上下文的bean。

spring.factories

1
2
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.jboost.springboot.starter.MyAutoConfig

指定了自动配置类(带包名的全路径类名)

springboot-usingstarter

该项目引用springboot-starter,调用MyService服务的项目,主类没什么特别的

1
2
3
4
5
6
7
@SpringBootApplication
public class SpringbootUsingstarterApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootUsingstarterApplication.class, args);
}
}

配置文件application.properties

1
2
3
my.disable=false
my.name=jboost
my.website=blog.jboost.cn

在测试类SpringbootUsingstarterApplicationTests中编写测试

1
2
3
4
5
6
7
@Autowired
private MyService myService;

@Test
public void testStarter(){
System.out.printf(myService.sayHi());
}

pom.xml中引入springboot-starter依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
 <dependencies>
<dependency>
<groupId>cn.jboost.springboot</groupId>
<artifactId>springboot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

运行,控制台会打印出 Hi jboost, welcome to visit blog.jboost.cn
将配置属性my.disable的值改为true或其它非false的值再运行测试代码试试,会报MyService bean找不到的错误,说明@ConditionalOnProperty注解生效了

本示例仅作实现自定义starter演示用,项目结构、命名都不够规范,仅供参考,项目实战starter在后面继续分享。

本文示例项目源码地址:
https://github.com/ronwxy/springboot-demos/tree/master/springboot-starter
https://github.com/ronwxy/springboot-demos/tree/master/springboot-usingstarter




我的个人博客地址:http://blog.jboost.cn
我的头条空间: https://www.toutiao.com/c/user/5833678517/#mid=1636101215791112
我的github地址:https://github.com/ronwxy
我的微信公众号:jboost-ksxy

——————————————————————————————————————————————————

微信公众号
欢迎关注我的微信公众号,及时获取最新分享