一、什么是Spring Boot Starter
1.1 自动装配
在介绍Spring Boot Starter之前,我们需要了解一下Spring Boot的自动装配机制,因为Spring Boot Starter的实现依赖于Spring Boot的自动装配机制。
SpringBoot在程序初始化时可以根据classpath、property属性、context中实例、以及运行容器特征等各种动态条件,来按需初始化相应的bean,并注册到IOC容器中。
SpringBoot启动的时候通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中所有的自动配置类,并对其进行加载,而这些自动配置类的类名都是以AutoConfiguration结尾来命名的,它实际上就是一个javaConfig形式的Spring容器配置类,它们都有一个@EnableConfigurationPerperties的注解,通过这个注解启动XXXProperties命名的类去加载全局配置中的属性,如server.port,而XXXProperties通过@ConfigurationProperties注解将全局配置文件中的属性与自己的属性进行绑定。
1.2 Spring Boot Starter概念
Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境( 条件)进行自动装配。使用者只需要依赖相应功能的Starter,无需做过多的配置和依赖,Spring Boot就能自动扫描并加载相应的模块。
Spring Boot Starter它提供了一个自动化配置类,一般命名为 XXXAutoConfiguration ,在这个配置类中通过条件注解来决定一个配置是否生效;然后,它还会提供一系列的默认配置,也允许开发者根据实际情况自定义相关配置;最后,通过类型安全的属性注入将这些配置属性注入进来,新注入的属性会代替掉默认属性。
例如,如果想使用Spring和JPA访问数据库,只需要项目中包含spring-boot-starter-data-jpa 依赖项,就可以正常使用。已有的Spring Boot Starter有很多,常用的有:
- spring-boot-starter:核心 starter,包括自动化配置支持,日志以及 YAML
- spring-boot-starter-test:SpringBoot 测试相关的 starter
- spring-boot-starter-web:构建 restful、springMVC 的 web应用程序的 starter
- spring-boot-starter-security:使用 Spring Security 的 starter
二、Spring Boot Starter编写
2.1 编写步骤
编写Starter非常简单,与编写一个普通的Spring Boot应用没有太大区别:
- 新建Maven项目,在项目的POM文件中定义使用的依赖;
- 新建配置类,写好配置项和默认的配置值,指明配置项前缀;
- 新建自动装配类,根据 @Conditional注解的条件,使用@Configuration和@Bean来进行自动装配;
- 新建spring.factories文件,指定Starter的自动装配类;
- 编写服务类,也就是我们starter要实现的功能;
2.2 案例
新建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 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.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.goldwind.example</groupId>
<artifactId>spring-boot-starter-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-starter-helloworld</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<!-- 核心 starter,包括自动化配置支持,日志以及 YAML -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 其中 spring-boot-configuration-processor 的作用是编译时生成 spring-configuration-metadata.json ,
此文件主要给IDE使用。如当配置此jar相关配置属性在 application.yml ,你可以用ctlr+鼠标左键点击属性名,IDE会跳转
到你配置此属性的类中。 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- spring boot 测试相关的 starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
这里顺带提一下spring-boot-stater-parent,
spring-boot-starter-parent 主要有如下作用:
- 定义了 Java 编译版本。
- 使用 UTF-8 格式编码。
- 继承自 spring-boot-dependencies,这个里边定义了依赖的版本,也正是因为继承了这个依赖,所以我们在写依赖时才不需要写版本号。
- 执行打包操作的配置。
- 自动化的资源过滤。
- 自动化的插件配置。
- 针对 application.properties 和 application.yml 的资源过滤,包括通过 profile 定义的不同环境的配置文件,例如 application-dev.properties 和 application-dev.yml。
新建配置类HelloWorldProperties.java:
package com.goldwind.example;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 新建配置类,写好配置项和默认的配置值,指明配置项前缀
*
* @author zy
* @since 2021/9/22
*/
@Data
@ConfigurationProperties(prefix = "example")
public class HelloWorldProperties {
// 姓名
private String name = "zy";
// 年龄
private Integer age = 18;
}
新建自动装配类HelloWorldAutoConfiguration.java:
package com.goldwind.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 新建自动装配类,使用@Configuration和@Bean来进行自动装配
*
* @author zy
* @since 2021/9/22
*/
@Configuration
@ConditionalOnClass(HelloWorldService.class)
@EnableConfigurationProperties(HelloWorldProperties.class)
public class HelloWorldAutoConfiguration {
@Autowired
private HelloWorldProperties properties;
@Bean
@ConditionalOnMissingBean
public HelloWorldService starterService() {
return new HelloWorldService(properties);
}
}
新建spring.factories(resources/META-INF路径下):
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.goldwind.example.HelloWorldAutoConfiguration
编写服务类HelloWorldService.java:
package com.goldwind.example;
/**
* 编写服务类,也就是我们starter要实现的功能
* 输出配置文件中的信息
*
* @author zy
* @since 2021/9/22
*/
public class HelloWorldService {
private HelloWorldProperties properties;
/**
* 构造函数
*/
public HelloWorldService(HelloWorldProperties properties) {
this.properties = properties;
}
public void helloWorld() {
System.out.println(String.format("我的名字是%s,我今年%d岁", properties.getName(), properties.getAge()));
}
}
执行mvn install,生成spring-boot-starter-helloworld.jar。
三、引用Starter
3.1 步骤
- 将Starter项目的依赖添加到我们自己的spring boot项目中;
- 在application.yml配置文件中添加配置信息;
3.2 案例
新建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 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.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.goldwind.example</groupId>
<artifactId>spring-boot-starter-helloworld-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.goldwind.example</groupId>
<artifactId>spring-boot-starter-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
新建DemoRunner.java:
package com.goldwind.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 通过实现ApplicationRunner或CommandLineRunner接口,可以实现应用程序启动完成后自动运行run方法
*
* @author zy
* @since 2021/9/22
*/
@Component
public class DemoRunner implements ApplicationRunner {
@Autowired
private HelloWorldService helloWorldService;
@Override
public void run(ApplicationArguments args) throws Exception {
helloWorldService.helloWorld();
}
}
新建DemoApplication.java:
package com.goldwind.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
修改配置文件application.yml:
example:
name: sf
age: 28