SpringBoot自定义Starter
一、为什么要自定义Starter
在我们的日常开发工作中,经常会有一些独立于业务之外的配置模块,我们经常将其放入到一个特定的包下,例如有个短信模块,如果另一个项目中也需要用到这块功能的时候,需要将代码硬生生地拷贝到另一个项目中去,重新集成一遍,非常的麻烦。如果我们这个短信模块功能封装成一个Starter,复用的时候只需要在将其POM文件中引用依赖就好了,再由SpringBoot为我们进行自动配置,就非常轻松了
二、自定义Starter案例
例如:
- 动态数据源
- 登录模块
- 基于AOP技术实现日志切面等等
1.自定义Starter的命名规范
SpringBoot提供的Starter以spring-boot-starter-xxx的方式命名
官方建议自定义的Starter使用xxx-spring-boot-starter的规则来进行命名,以区分SpringBoot生态提供的Starter
2.自定义Starter的实现
整个过程分为两部分:
-
自定义Starter
-
新建maven jar工程,工程名为lj-spring-boot-starter,并导入依赖spring-boot-autoconfigure
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.2.9.RELEASE</version> </dependency> </dependencies>
-
编写JavaBean
@Configuration @EnableConfigurationProperties @ConfigurationProperties(prefix = "simpleuserbean") public class SimpleUserBean { private int name ; private String password; public int getName() { return name; } public void setName(int name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "SimpleUserBean{" + "name=" + name + ", password='" + password + '\'' + '}'; } }
-
编写自动配置类
@Configuration public class MyAutoConfiguration { static { System.out.println("MyAutoConfiguration init..."); } @Bean public SimpleUserBean simpleUserBean(){ return new SimpleUserBean(); } }
-
创建一个META-INF/spring.factories文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vwoZZfIu-1672973427629)(
)]将自定义的自动配置类全限定名写入进去
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.lj.config.MyAutoConfiguration
至此自定义一个starter就完成了!!
-
-
使用Starter
-
导入自定义的starter的依赖
<dependency> <groupId>org.example</groupId> <artifactId>lj-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
-
在全局配置文件中配置属性值
simpleuserbean.name=liujun simpleuserbean.password=132123
-
编写测试方法
//测试自定义Starter @Autowired private SimpleUserBean simpleUserBean; @Test public void test2(){ System.out.println(simpleUserBean); }
但此处还有个小问题,如果有一天我们不需要启动工程的时候自动配置SimpleUserBean了呢?可能大家会想,那简单啊,将POM文件中的依赖注释掉就好了,的确,这是一种方案,但是也确实有点Low。
3.SpringBoot热插拔技术
大家还记得我们经常用在启动类Application上方的@EnableXXX嘛?(例如@EnableRabbit)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u4STmfNG-1672973427631)(
)]其实这个@EnableXXX注解就是一种热插拔技术,加了这个注解之后就可以启动对应的starter,当不需要对应的starter的时候只需要把这个注解注释掉就行了,是不是很优雅呢?那这个注解是如何实现的呢?
-
在starter工程中新增一个标记类ConfigMarker
public class ConfigMarker{ }
-
新增EnableRegisterServer注解
@Target({ElementType.TYPE}) //表示这个注解可以使用在类、接口、属性等等 @Retention(RetentionPolicy.RUNTIME) //这个是设置当前的注解的生命周期 @Import({ConfigMarker.class}) //将某个组件类生成实例 public @interface EnableRegisterServer { }
-
改造MyAutoConfiguration新增条件注解@ConditionalOnBean(ConfigMarker.class),@ConditionOnBean这个是个条件注解,意思是需要存在ConfigMarker对象,被标注的类才会被进行实例化;
@Configuration @ConditionalOnBean(ConfigMarker.class) //在上下文中必须要存在ConfigMarker.class这个类才会让当前自动配置类生效 public class MyAutoConfiguration { static { System.out.println("MyAutoConfiguration init..."); } @Bean public SimpleUserBean simpleUserBean(){ return new SimpleUserBean(); } }
-
最后在启动类上新增@EnableRegisterServer注解
@EnableRegisterServer @SpringBootApplication public class ImAppApplication{ public static void main(String[] args){ SpringApplication.run(ImApplication.class , args); } }
public class ImAppApplication{
public static void main(String[] args){
SpringApplication.run(ImApplication.class , args);
}
}
-