starter的作用
我们使用springboot ,引入各种各样的starter来简化开发过程。我们也可以编写自定义starter,封装一些通用组件来被别的项目引用
如何自定义starter
网上最广泛使用的是spring.factories 方式,但高版本上(2.7.11) 已经改文件名了(META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports),处于两者并存的方式。
我们先来介绍spring.factories 方式
spring.factories 方式
官方文档地址:7.9. Creating Your Own Auto-configuration
7.9. Creating Your Own Auto-configuration
If you work in a company that develops shared libraries, or if you work on an open-source or commercial library, you might want to develop your own auto-configuration. Auto-configuration classes can be bundled in external jars and still be picked-up by Spring Boot. 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.
如果你想要在公司开发共享的库,或者为开源、商业库工作,你可能需要开发自己的自动配置。
具体步骤是:
- 新建springboot工程
- 开发配置相关的Config
- 发布部署
1. 新建springboot工程
根据推荐的命名规范,springboot官方的starter叫 spring-boot-xxx-starter, 自定义开发的就叫 xxx-spring-boot-starter, 假设我们需要一个公用邮件依赖的starter mail-spring-boot-starter:
由于可选的最低版本是2.7.11 就先用它
之后就把 springboot 版本改为2.6.14
2. 开发配置相关的Config
根据描述, 需要在META-INF下创建一个 spring.factories的文件,并把自定义config配置进去:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.mailspringbootstarter.config.MailSenderConfig
You almost always want to include one or more
@Conditionalannotations on your auto-configuration class. The@ConditionalOnMissingBeanannotation is one common example that is used to allow developers to override auto-configuration if they are not happy with your defaults.
你几乎总是会用到 @Conditional 注解在自动配置类上。使用@ConditionalOnMissingBean 让开发者可以覆盖掉你的自动配置。 于是就在该类加上这个注解。
The
@ConditionalOnClassand@ConditionalOnMissingClassannotations let@Configurationclasses be included based on the presence or absence of specific classes. Due to the fact that annotation metadata is parsed by using ASM, you can use thevalueattribute to refer to the real class, even though that class might not actually appear on the running application classpath. You can also use thenameattribute if you prefer to specify the class name by using aStringvalue.
Tip: If you use
@ConditionalOnClassor@ConditionalOnMissingClassas a part of a meta-annotation to compose your own composed annotations, you must usenameas referring to the class in such a case is not handled.
使用ConditionalClass 注解来指定存在或不存在类的时候,Configuration来加载哪个.我们这里用@ConditionalOnClass 即存在。 使用这个注解必须加类的名字.
然后创建需要的配置属性,Configuration keys这里叫MailProperties
@ConfigurationProperties(prefix = "mail")
public class MailProperties {
private String server;
private String from;
private String username;
private String password;
// getters and setters
Make sure to trigger meta-data generation so that IDE assistance is available for your keys as well. You may want to review the generated metadata (
META-INF/spring-configuration-metadata.json) to make sure your keys are properly documented. Using your own starter in a compatible IDE is also a good idea to validate that quality of the metadata.
确定元数据生成,需要引入相对应的库。 所以在pom中添加相关依赖:
B.3. Generating Your Own Metadata by Using the Annotation Processor
You can easily generate your own configuration metadata file from items annotated with
@ConfigurationPropertiesby using thespring-boot-configuration-processorjar. The jar includes a Java annotation processor which is invoked as your project is compiled.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
The “autoconfigure” Module
你也可以选择另外一个jar
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
只不过需要构建时候加上过滤:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
一个报错:
需要开启这个@EnableConfigurationProperties注解
最终的 MailSenderConfig
@Configuration
@ConditionalOnMissingBean({MailSender.class})
@EnableConfigurationProperties({MailProperties.class})
public class MailSenderConfig {
@Bean
public MailSender mailSender() {
return new MailSender();
}
}
mailsender:
public class MailSender {
@Autowired
private MailProperties mailProperties;
public void send(String receivers, String subject, String content) {
System.out.println("验证server " + mailProperties.getServer() + ", username-->" + mailProperties.getUsername());
System.out.println("receivers-->" +receivers +", subject-->" + subject + ", content-->" + content);
}
}
代码结构:
3. 发布部署
命令行直接 mvn clean install
找到自己配置的maven仓库地址:
注意, build要加参数<classifier>exec</classifier>,防止引用不到
最终的pom.xml:
<?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.14</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>mail-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mail-spring-boot-starter</name>
<description>mail-spring-boot-starter</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
其他工程引入
新建一个springboot工程,同样使用 2.6.14版本 引入刚才新建的包:
<dependency>
<groupId>com.example</groupId>
<artifactId>mail-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
测试里写:
@SpringBootTest
class MailSenderTests {
@Autowired
private MailSender mailSender;
@Test
void test() {
mailSender.send("hellojack@gmail.com", "send you an apple gift card", "hello world");
}
}
运行然后看输出:
完成
再来看新版本的写法
新版本 2.7.11 配置文件有了修改: 7.9 Creating Your Own Auto-configuration
不再使用spring.factories 而是使用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 来作为配置,当然使用spring.factories 也是兼容的
我们照着改一下:
首先删掉 spring.factories文件,在META-INF新建spring文件夹,然后新建 xxxx文件,并填入自动配置:
sender做下修改区分:
public void send(String receivers, String subject, String content) {
System.out.println("第二种方式验证server " + mailProperties.getServer() + ", username-->" + mailProperties.getUsername());
System.out.println("第二种方式receivers-->" +receivers +", subject-->" + subject + ", content-->" + content);
}
记得把springboot版本改为 2.7.11 , 包括测试工程
然后打包 mvn clean install
测试
验证成功