1、简介
SpringBoot 最强大的功能就是把我们常用的场景抽取成了一个个starter(场景启动器),我们通过引入springboot 为我提供的这些场景启动器,我们再进行少量的配置就能使用相应的功能。即使是这样,springboot也不能囊括我们所有的使用场景,往往我们需要自定义starter,来简化我们对springboot的使用。
我们将这些可独立于业务代码之外的功配置模块封装成一个个starter,复用的时候只需要将其在pom中引用依赖即可,SpringBoot为我们完成自动装配。
2、自定义starter的命名规则
SpringBoot提供的starter以spring-boot-starter-xxx
的方式命名的。官方建议自定义的starter使用xxx-spring-boot-starter
命名规则。以区分SpringBoot生态提供的starter。
2.1 官方命名空间
- 前缀:spring-boot-starter-xxx
- 模式:spring-boot-starter-模块名
- 举例:spring-boot-starter-web、spring-boot-starter-jdbc
2.2 自定义命名空间
- 后缀:xxx-spring-boot-starter
- 模式:模块-spring-boot-starter
- 举例:mybatis-spring-boot-starter
3、自定义starter实现
3.1 新建工程
命名为demo-spring-boot-start
项目结构如下:
3.2 pom依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <?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 https://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.6.1</version> <relativePath/> </parent> <groupId>com.lyq</groupId> <artifactId>demo-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo-spring-boot-starter</name> <description>Demo project for Spring Boot starter</description> <properties> <java.version>1.8</java.version> </properties> <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-starter</artifactId> </dependency> </dependencies> </project>
|
3.3 定义配置信息映射的实体类
@ConfigurationProperties(prefix = "demo")
它可以把相同前缀的配置信息通过配置项名称映射成实体类,比如我们这里指定 prefix = "demo"
这样,我们就能将以demo为前缀的配置项拿到了。
ps:其实这个注解很强大,它不但能映射成String或基本类型的变量。还可以映射为List,Map等数据结构。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.lyq.starter.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "demo") public class DemoProperties { private String sayWhat; private String toWho;
public String getSayWhat() { return sayWhat; }
public void setSayWhat(String sayWhat) { this.sayWhat = sayWhat; }
public String getToWho() { return toWho; }
public void setToWho(String toWho) { this.toWho = toWho; } }
|
3.4 定义一个service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.lyq.starter.service;
import com.lyq.starter.properties.DemoProperties;
public class DemoService { DemoProperties demoProperties;
public DemoProperties getDemoProperties() { return demoProperties; }
public void setDemoProperties(DemoProperties demoProperties) { this.demoProperties = demoProperties; }
public String say(String name){ return name + "对" + demoProperties.getToWho() + "说:“" + demoProperties.getSayWhat() + "”"; } }
|
3.5 定义配置类
这里,我们将DemoService
类定义为一个Bean,交给Ioc容器。
@Configuration
声明一个类作为配置类,代替xml文件。ps:通常 @Configuration
和 @Bean
是一起使用的
@EnableConfigurationProperties
注解。该注解是用来开启对3步骤中 @ConfigurationProperties
注解配置Bean的支持。
当然了,也可以在 @ConfigurationProperties
注解的类上添加 @Configuration
或者 @Component
注解
@ConditionalOnProperty
注解控制 @Configuration
是否生效。简单来说也就是我们可以通过在yml配置文件中控制 @Configuration
注解的配置类是否生效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package com.lyq.starter.config;
import com.lyq.starter.properties.DemoProperties; import com.lyq.starter.service.DemoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration @EnableConfigurationProperties(DemoProperties.class) @ConditionalOnProperty( prefix = "demo", name = "isopen", havingValue = "true" ) public class DemoAutoconfiguration { @Autowired private DemoProperties demoProperties;
@Bean public DemoService demoService(){ DemoService demoService = new DemoService(); demoService.setDemoProperties(demoProperties); return demoService; } }
|
3.6 重点:创建spring.factories
在resource目录下,新建META-INF文件夹,然后创建spring.factories文件。
目录结构如下:
在该文件中加入如下配置,该配置指定上步骤中定义的配置类为自动装配的配置:
1 2 3
| org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.lyq.starter.config.DemoAutoconfiguration
|
3.7 生成starter
在demo-spring-boot-starter工程中,使用terminal终端执行mvn clean
、mvn install
或者直接点击运行maven插件:
至此,一个自定义的starter新鲜出炉。(本人配置了mvn本地仓库,看下本地仓库中starter):
3.8 测试
3.8.1 新建测试工程
3.8.2 引入自定义start依赖
1 2 3 4 5
| <dependency> <groupId>com.lyq</groupId> <artifactId>demo-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
|
3.8.3 配置application.yml
1 2 3 4
| demo: isopen: true to-who: 李四 say-what: 自定义的starter测试成功
|
3.8.4 编写测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.lyq.controller;
import com.lyq.starter.service.DemoService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;
@RestController public class StarterTestController { @Resource(name = "demoService") private DemoService demoService;
@GetMapping("/say") public String sayWhat(){ return demoService.say("张三"); } }
|
3.8.5 验证结果
点击这里查看源码