本文记录快速实现自定义starter,过程中会跳过一些原理。建议了解一些springboot的自动装配原理再来食用效果更佳,当然了不了解也没关系。
有些小伙伴可能对于自定义starter有点陌生,其实大家在日常开发过程中或多或少接触过,比如我们常用的mybatis-plus,它就是一个官方制作的starter,它可以提供一些api和配置一些参数来方便我们调用。我们不用很在意为什么我们使用了这样的api就可以完成调用,帮我们屏蔽了一些细节。
我们大致了解了starter可以帮我们做什么了。可能也会有人说那么为什么不直接引入jar包呢?本篇章不做解释,小伙伴们可以使用文心一言来搜索一下,输入以下问题即可。
自定义starter与直接导入jar包有何区别?
让我们直接步入正题吧。首先打开idea,创建一个springboot项目,什么依赖都不需要勾选,直接创建。 创建好之后,删掉启动类和test文件夹,并添加一些依赖,如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 属性的时候用-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- 打包出现没有mainClass异常解决方法-->
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
全部的依赖,没有额外的依赖
此时我们假设一个很简单的需求,starter提供一些简单的api来返回我们配置在第三方的配置参数 只是用来演示并没有实际意义。
我们用来接收配置文件的实体类
@ConfigurationProperties(prefix = "auto-client") // properties或者是yml文件中自定义的变量,以auto-client开头
public class AutoProperties {
private String name;
private String address;
// 省略一些get set方法
}
starter提供的方法/服务
public class AutoService {
@Resource
private AutoProperties autoProperties;
public String getName(){
return autoProperties.getName();
}
public String getAddress(){
return autoProperties.getAddress();
}
}
配置类
@Configuration
@EnableConfigurationProperties(AutoProperties.class)
public class AutoConfig {
@Bean
public AutoService autoService(){
return new AutoService();
}
}
此时就有一个问题了,那么该如何使得别的项目依赖了该starter可以直接获取到AutoService并调用其中的api呢?那么此时就需要使用到springboot的自动装配的原理了。可能有的小伙伴并不是很清楚,建议先了解该原理,可以更好的理解。当然也可以看完本章内容之后,在进行了解。假如你不太了解,此时我们可以参考别人是如何写的,比如mybatis-plus,此时引入该依赖,可以看到
当然了,如果移除掉该依赖,那么我们也能找到一些蛛丝马迹
此时我们需要在在上述提到的META-INF文件夹直接拷贝到我们的resources目录下,然后进行删减只保留 additional-spring-configuration-metadata.json和spring.factories
additional-spring-configuration-metadata.json是用来提示的,我们在日常开发过程中估计都见过,只不过可能不太清楚。如图所示,大家是不是很熟悉,这个文件的作用就是这样的。接下来我们呢做一些简单的配置
{
"properties": [
{
"name": "auto-client.name", -- 配置文件的key
"type": "java.lang.String", -- 配置文件key后面接的数据是什么类型的
"description" : "学生名称", -- 描述是干什么用的
"defaultValue": "大耳朵糊涂" -- 默认值,就跟上面的8080一样
},{
"name": "auto-client.address",
"type": "java.lang.String",
"description" : "地址",
"defaultValue": "苏州"
}
]
}
spring.factories是用来自动导入的,如果有的小伙伴们不知道自动装配的话,可以自行了解哦,关键词springboot的自动装配 内容为
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.hu.config.AutoConfig -- 自动装配的路径
此时我们就可以直接使用idea打包。点击test 然后点击图中2跳过test,然后双击install进行打包。此时我们就可以在我们的本地maven仓库中看到我们的jar包了,当然也可以在target目录查看到我们打成的jar包
此时我们还是相同的手法创建另一个springboot项目,还是什么依赖都不要勾选,直接完成。然后在pom文件中导入我们制作好的starter有的小伙伴们不知道如何导入,我教大家一个方法,直接拷贝如图红圈圈中的三行。
然后在我们的测试自定义starter pom文件中引入,然后刷新maven即可
此时我们就可以看到我们的starter被导入了我们的项目中了
接下来我们开始进行一些配置来完成我们的需求(调用starter来返回配置在properties文件中的值),此时就可以发现我们在starter中配置的提示已经起到了作用了
使用最简单的测试方法
@SpringBootApplication
public class TestStartDemoApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(TestStartDemoApplication.class, args);
AutoService autoService = context.getBean(AutoService.class); // 因为我们的starter已经自动装配了,所以是可以获取到我们的bean的
System.out.println(autoService.getAddress());
}
}
此时小伙伴们就可以看到控制台打印出了我们的姓名了哦。小伙伴们学废了嘛。
本文到此结束,可能有些错误或者是描述不清楚的地方,希望大佬多多指点。
更新:在 Spring Boot 2.7.0 及以上版本中发生了一些变化,如下图所示(建议对比下图与低版本的截图,特别是关注 spring.factories 文件的内容)。我们会发现 org.springframework.boot.autoconfigure.EnableAutoConfiguration 这一行在旧版本中存在,但在新版本中被移除了。不过,高版本中多出来的一个文件名看起来非常类似这一行代码。
如果选择这种方式进行注入,只需在文件内容中明确写出所需注入类的全限定名即可轻松实现。值得注意的是,较高版本依然兼容这种较低版本的写法,但反过来则不成立。对此感兴趣的朋友们可以深入探索两种方法之间的差异;本文将不再赘述此部分内容。