笔者语录: 话不多说,直接开干。
spring-boot-starter的关键:
@SpringBootApplication注解源码是这样的:
@ComponentScan注解的作用是把(@SpringBootApplication所在的)入口类所在的包(及其子包)下的所有被@Component注解(或拓展了@Component的注解)标记了的bean注册到spring容器中
。那么,处于@ComponentScan扫描范围外的bean是
如何注册到容器中的呢,那就是靠@EnableAutoConfiguration来实现注册的
。
@EnableAutoConfiguration注解的作用是:将普通jar包资源目录下的META-INF/spring.factories文件里面配置的键为org.springframework.boot.autoconfigure.EnableAutoConfiguration的类纳入考虑范围内,考虑是否将这个(些)类注册进Spring容器。如果这个(些)类被@Component注解(或拓展了@Component的注解)标记了,且满足@Conditional…条件(如果有@Conditional…的话),那么将其注册进Spring容器,如果不满足条件,那么就不注册进Spring容器。
- 注:追踪源码可知,在@EnableAutoConfiguration注解里面启用了
SpringBoot的
AutoConfigurationImportSelector类, 在AutoConfigurationImportSelector类中的getAutoConfigurationEntry
方法里,调用了Spring的SpringFactoriesLoader#loadFactories
来加载资源jar包下的META-INF/spring.factories
文件里的key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的value集合
。 - 注:@Conditional…条件有:
编写spring-boot-starter(示例):
提示: artifactId的命名需要注意,spring-boot-starter-xxx是SpringBoot官方保留
的starter命名方式;业界
自定义的starter的命名,一般用xxx-spring-boot-starter
。
第一步:创建一个SpringBoot项目,并简单改造。
- 在pom.xml中引入spring-boot-configuration-processor和spring-boot-autoconfigure(
完整pom.xml见下方
)。 - 去掉pom.xml中的打可执行的jar包的插件(
完整pom.xml见下方
)。
注:普通的jar包与可执行的jar包的class文件路径是不一样的。
注:只要去掉这个打包插件就行;去不去掉SpringBoot的启动类都没关系,不过出于洁癖考虑,推荐同时去掉启动类。
注:这里 给出完整的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.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.pingan</groupId> <artifactId>custom-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> <name>custom-spring-boot-starter</name> <description>编写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-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <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-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> </project>
第二步:编写“管理”类。这个类用来管理:启用哪些被@ConfigurationProperties标记了的类、注册哪些Bean等等。
import com.pingan.customstarter.service.LogicHandler;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* starter管理类
*
* @author JustryDeng
* @date 2020/4/4 14:48:27
*/
@Configuration
@EnableConfigurationProperties(CustomAutoConfiguration.Properties.class)
@ConditionalOnProperty(value = "coder.info.enabled", havingValue = "true")
public class CustomAutoConfiguration {
@Bean
public LogicHandler logicHandler() {
return new LogicHandler();
}
/**
* 配置信息
*
* @author JustryDeng
* @date 2020/4/4 14:38:05
*/
@Setter
@Getter
@ConfigurationProperties(prefix = "coder.info")
public static class Properties {
/** 是否启用 */
private boolean enabled = false;
/** 姓名 */
private String name;
/** 爱好 */
private String motto;
}
}
注:这个管理类不是必须的
。如果不创建这个管理类来统一管理那些可能需要注册进容器的类的话,那么就需要在第四步(见下文)的spring.factories文件里,指定这些类
了;无疑,创建管理类更方便,更利于维护。
第三步:编写一个业务逻辑相关的类(见:第二步注册进Spring的那个bean),用来做需要的逻辑。
第四步:在资源目录下的META-INF/spring.factories文件(无则创建)里,通过org.springframework.boot.autoconfigure.EnableAutoConfiguration指定要注册进容器的类。
注:指定后,这个类不是说一定会被注册进容器,其必须被@Component注解(或拓展了@Component的注解)标记了,并且如果其有@Conditional…条件的话,那么还需要满足条件,才会被注册进Spring容器。
注:如果需要注册多个类,那么使用逗号隔开,如:
第五步:mvn install到本地仓库(,mvn deploy到远程仓库),供其它项目使用。
测试一下:
- 第一步: 创建一个新的SpringBoot项目,并在pom.xml中,引入我们编写的starter。
- 第二步: 在application.yml中配置参数,使触发启动starter中的配置类。
- 第三步: 编写测试代码,并测试。
- 启动项目,控制台输出:
由此可见,自定义spring-boot-starter成功!
^_^ 如有不当之处,欢迎指正
^_^ 参考链接
https://www.cnblogs.com/yuansc/p/9088212.html
https://www.cnblogs.com/softidea/p/6886460.html
https://blog.csdn.net/SkyeBeFreeman/article…
^_^ 参考资料
《Spring Boot Cookbook》
^_^ 测试代码托管链接
https://github.com/JustryDeng/…spring-boot-starter…
^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng