前言
今天看到了一道面试题,如何实现一个自定义的 SpringBoot starter
,或者说,SpringBoot
如何加载我们自己的 jar
包?其实,仔细想想本质是考察 SpringBoot
的自动配置原理,了解了其自动配置原理即可实现 SpringBoot
自定义 starter
SpringBoot
自动配置原理:https://blog.csdn.net/weixin_38192427/article/details/115178359
SpringBoot
自定义 starter
创建多模块项目
SpringBoot
的官方 starter
命名方式为 spring-boot-starter-xxx
如 spring-boot-starter-quartz
,SpringBoot
官方建议第三方 starter
的命名方式一般为 xxx-spring-boot-starter
创建一个 custom-spring-boot-starter
项目,项目下面新建两个模块
hello-spring-boot-starter
(场景启动器,普通Maven
工程)hello-spring-boot-starter-autoconfigure
(自动配置包,需用到Spring Initializr
创建的Maven
工程)
项目编码
custom-spring-boot-starter
父模块 Maven
依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.9.RELEASE</version>
<relativePath></relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
</dependencies>
hello-spring-boot-starter-autoconfigure
子模块
HelloProperties
属性映射类
@ConfigurationProperties(prefix = "hello")
public class HelloProperties {
private String username;
private String password;
// 省略 get/set 方法......
}
@ConfigurationProperties
:负责将配置文件里的配置信息绑定映射到实体bean
上
HelloService
业务逻辑类
public class HelloService {
private String username;
private String password;
public String haloHello() {
return "用户名为:" + username + ">>>" + "密码为:" + password;
}
// 省略 get/set 方法......
}
HelloServiceAutoConfiguration
配置类
@Configuration
@EnableConfigurationProperties(value = HelloProperties.class)
@ConditionalOnClass(value = HelloService.class)
@ConditionalOnProperty(prefix = "hello", value = "enabled", matchIfMissing = true)
public class HelloServiceAutoConfiguration {
@Autowired
private HelloProperties helloProperties;
@Bean
@ConditionalOnMissingBean(value = HelloService.class)
public HelloService helloService() {
System.out.println("Execute Create New Bean");
HelloService helloService = new HelloService();
helloService.setUsername(helloProperties.getUsername());
helloService.setPassword(helloProperties.getPassword());
return helloService;
}
}
@EnableConfigurationProperties(value = HelloProperties.class)
:负责将指定的bean
注册到Spring
容器中@ConditionalOnProperty(prefix = "hello", value = "enabled", matchIfMissing = true)
:当配置文件中hello.enabled = true
时进行自动配置,如果没有设置此值就默认使用matchIfMissing
指定的值
@Conditional
条件注解
@ConditionalOnBean
:当给定的bean
存在时,则实例化当前bean
@ConditionalOnMissingBean
:当给定的bean
不存在时,则实例化当前bean
@ConditionalOnClass
:当给定的类名在类路径上存在时,则实例化当前bean
@ConditionalOnMissingClass
:当给定的类名在类路径上不存在时,则实例化当前bean
@ConditionalOnExpression
:当表达式为true
的时候,才会实例化一个bean
创建 spring.factories
文件
spring.factories
文件内容如下
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.example.config.HelloServiceAutoConfiguration
- 如果有多个自动配置类,则用
,
隔开 ,
后不要有空格之类的符号,就只写该类的全路径,不然会出现无法找到此bean
的错误
Maven
打包
用 Maven
插件,将该工程 install
到本地 Maven
仓库。记得要把 hello-spring-boot-starter-autoconfigure
的 test
包删除
自定义 starter
的使用
Maven
依赖
<dependencies>
<!--引入自定义的starter-->
<dependency>
<groupId>org.example</groupId>
<artifactId>hello-spring-boot-starter-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--lombok 插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
application.properties
配置文件
在项目 hello-spring-boot-starter
中添加配置文件 application.properties
server.port=8080
hello.username=xiaoming
hello.password=123123
HelloController
测试接口类
@Slf4j
@Controller
public class HelloController {
@Autowired
private HelloService helloService;
@Autowired
private HelloProperties helloProperties;
@GetMapping(path = "/hello")
@ResponseBody
public String sayHello() {
log.info("用户名为:" + helloProperties.getUsername());
log.info("密码为:" + helloProperties.getPassword());
return helloService.haloHello();
}
}
测试结果
控制台结果
postman
接口返回结果
版权声明:本文为weixin_38192427原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。