SpringBootStarter机制
SpringBoot由众多Starter组成(一系列的自动化配置的starter插件),SpringBoot之所以流行,也是因为starter。starter是SpringBoot非常重要的一部分,可以理解为一个可拔插式的插件,正是这些starter使得使用某个功能的开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由SpringBoot自动通过classpath路径下的类发现需要的Bean,并织入相应的Bean。
例如,
你想使用Reids插件,那么可以使用spring-boot-starter-redis;
如果想使用MongoDB,可以使用spring-boot-starter-data-mongodb
简而言之,starter就是一个外部的项目,我们需要使用它的时候就可以在当前springboot项目中 引入它
为什么要自定义starter
开发过程中,经常会有一些独立于业务之外的配置模块。如果我们将这些可独立于业务代码之外的功能配置模块封装成一个个starter,复用的时候只需要将其在pom中引用依赖即可,SpringBoot为我们完成自动装配.(方便复用)
自定义starter的命名规则
SpringBoot提供的starter以spring-boot-starter-xxx的方式命名的。
官方建议自定义的starter使用xxx-spring-boot-starter命名规则。
以区分SpringBoot生态提供的starter
自定义starter的案例
以下案例是开发中遇到的部分场景
▲ 动态数据源。
▲ 登录模块。
▲ 基于AOP技术实现日志切面。
………
自定义starter代码实现
整个过程分为两部分:
1、自定义starter
2、使用starter
1、自定义starter
1、新建maven jar工程,工程名为zdy-spring-boot-starter,导入依赖:
导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
</dependencies>
2、编写javaBean
@EnableConfigurationProperties(SimpleBean.class)
@ConfigurationProperties(prefix = "simplebean")
// 将配置文件中以simplebean为前缀的都注入到这个类中
public class SimpleBean {
// simplebean是前缀,当在配置文件赋值的时候用得到
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "SimpleBean{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
3、编写配置类MyAutoConfiguration
@Configuration
public class MyAutoConfiguration {
/*静态代码块,当进入这个类的时候可以打印*/
static {
System.out.println("MyAutoConfiguration init....");
}
/*标注了@Bean注解,启动过程中就会生成Bean 对象存入到容器中
在自动配置的时候会调用simpleBean方法,并将其实例对象存放到ioc容器中。
等下使用这个starter的时候,可以直接的从自动配置类里面获取现在创建出来的simpleBean
*/
@Bean
public SimpleBean simpleBean(){
return new SimpleBean();
}
}
4、resources下创建/META-INF/spring.factories
注意:META-INF是自己手动创建的目录,spring.factories也是手动创建的文件,在该文件中配置自 己的自动配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.slin.edu.confige.MyAutoConfiguration
上面这句话的意思就是SpringBoot启动的时候会去加载我们的simpleBean到IOC容器中。这其实 是一种变形的SPI机制
自定义starter中为什么要建/META-INF/spring.factories,是因为SpringBoot运行过程中,会去加载classpath下所有的能找到的spring.factories文件。并且读取里面配置文件配置类的路径,根据这些路径来实现自动配置,如想将自定义的类进行自动配置,则需要将他们设置在spring.factories里面,设置为自动配置类。
2、使用自定义starter
1、导入自定义starter的依赖
<dependency>
<groupId>com.slin.edu</groupId>
<artifactId>zdy-spring-boot-starter</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
2、 在全局配置文件中配置属性值
simplebean.id=1
simplebean.name=自定义starter
3、编写测试方法
直接在TestController写
@RestController
public class TestController {
@Autowired
SimpleBean simpleBean;
@GetMapping("/test")
public String test(){
return simpleBean.toString() ;
}
}
4、运行看效果
正常返回
但此处还有一个问题,如果有一天我们不想要启动工程的时候自动装配SimpleBean呢?可能有的 同学会想,那简单啊,我们去pom中把依赖注释掉,的确,这是一种方案,但为免有点Low
3、改造实现可插拔的的starter
还记得我们经常会在启动类Application上面加@EnableXXX注解吗?
其实这个@Enablexxx注解就是一种热拔插技术,加了这个注解就可以启动对应的starter,当不需 要对应的starter的时候只需要把这个注解注释掉就行,是不是很优雅呢?那么这是如何实现的 呢?
1、 新增标记类ConfigMarker
public class ConfigMarker {
}
2、 新增EnableRegisterServer注解
@Target({ElementType.TYPE})//作用范围
@Retention(RetentionPolicy.RUNTIME)// 整个运行期间都可用
@Import({ConfigMarker.class})// SpringBoot启动过程中自动注入ConfigMarker类
public @interface EnableRegisterServer {
}
3、改造 MyAutoConfiguration
新增条件注解 @ConditionalOnBean(ConfigMarker.class) ,
@ConditionalOnBean 这个是条件注解,
意思代表只有当前上下文中含有 ConfigMarker 对象,被标注的类才会被实例化。
@Configuration
@ConditionalOnBean(ConfigMarker.class)
public class MyAutoConfiguration {
/*静态代码块,当进入这个类的时候可以打印*/
static {
System.out.println("MyAutoConfiguration init....");
}
/*标注了@Bean注解,启动过程中就会生成Bean 对象存入到容器中*/
@Bean
public SimpleBean simpleBean(){
return new SimpleBean();
}
}
4、使用方进行改造service工程
@SpringBootApplication
@EnableRegisterServer
public class SpringDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDemoApplication.class, args);
}
}