starter背景
Spring Boot它已成为后端开发的必要技能之一Spring Boot有一个非常重要的机制(starter机制)。
starter能够抛弃以前繁杂的配置,将其统一集成进starter,只需使用即可maven引入相应的starter依赖即可,Spring Boot可自动扫描要加载的信息,并启动相应的默认配置。
starter让我们摆脱各种依赖库的处理和各种配置信息的麻烦。SpringBoot会自动通过classpath发现路径下的类所需的Bean,并注册进IOC容器。Spring Boot为日常企业应用研发提供各种场景spring-boot-starter依赖模块。所有这些依赖模块都遵循约定的默认配置,并允许我们调整这些配置,即遵循“协议大于配置”的理念。
我们经常看到或使用各种各样的东西xxx-starter。比如以下几种:
Spring Boot starter原理
总的来说,无非是会Jar包作为项目的依赖,引入项目。现在难度增加的原因是我们引入的是Spring Boot Starter,所以我们需要理解Spring Boot对Spring Boot Starter的Jar包是怎么加载的?下面简单说一下。
SpringBoot 开始时会依赖 starter 在包里找 //META-INF/spring.factories 文件,然后根据文件中配置的 Jar 包去扫描项目所依赖的 Jar 包,类似 Java 的 SPI 机制。
可用于细节@Conditional 系列注释实现了更准确的配置加载Bean的条件。
JavaSPI 实际上是“基于接口的编程 策略模式 配置文件”动态加载机制的组合实现。
自定义starter的条件
假如想定制自己Starter,实现自动化配置的首选需要满足以下两个条件:
自动配置项目所需的配置信息,即依赖环境的自动加载; 可根据项目提供的信息自动生成Bean,并且注册到Bean管理容器;实现自定义starter
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><version>2.0.0.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><version>2.0.0.RELEASE</version><optional>true</optional></dependency></dependencies>根据需要自定义Starter实现过程大致如下(我定义的)Starter为例):
定义XxxProperties类别、属性配置类别,完成属性配置相关操作,如设置属性前缀,用于application.properties中配置。
TianProperties代码:
importorg.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix="spring.tian")publicclassTianProperties{privateStringname;privateintage;privateStringsex="M";//省略getset方法}创建XxxService类,完成相关操作逻辑 。
TianService代码:
publicclassTianService{privateTianPropertiesproperties;publicTianService(){}publicTianService(TianPropertiesuserProperties){this.properties=userProperties;}publicvoidsayHello(){System.out.println("hi,我叫:" properties.getName() ",今年" properties.getAge() "岁" ",性别:" properties.getSex());}}定义XxxConfigurationProperties用于完成类、自动配置类Bean创建等工作。
TianServiceAutoConfiguration代码:
@Configuration@EnableConfigurationProperties(TianProperties.class)@ConditionalOnClass(TianService.class)@ConditionalOnProperty(prefix="spring.tian",value="enabled",matchIfMissing=true)publicclassTianServiceAutoConfiguration{@AutowiredprivateTianPropertiesproperties;@Bean@ConditionalOnMissingBean(TianService.class)publicTianServicetianService(){returnnewTianService(properties);}}在resources下创建目录META-INF,在 META-INF 创建 目录spring.factories,在SpringBoot项目的自动配置类别将根据本文件加载。
「spring.factories中配置」
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.tian.TianServiceAutoConfiguration把上面这个starter工程打成jar包:
使用自定义starter
创建一个Spring Boot项目test,整个项目如下图所示:
在项目中定制自己starter添加pom依赖
<dependency><groupId>com.tian</groupId><artifactId>spring-boot-tian-starter</artifactId><version>1.0-SNAPSHOT</version></dependency>TestApplication启动类
@SpringBootApplication@EnableEurekaServerpublicclassTestApplication{publicstaticvoidmain(String[]args){SpringApplication.run(TestApplication.class,args);}}application.properties中配置
spring.tian.name=tianspring.tian.age=22spring.tian.sex=M写一个TestController.java类
RestController@RequestMapping("/my")publicclassTestController{@ResourceprivateTianServicetianService;@PostMapping("/starter")publicObjectstarter(){tianService.sayHello();return"ok";}}自定义starter打成的jar依赖进来后,
可以看中多了一个。json的文件。
最后启动项目,输入
http://localhost:9091/my/starter
controller成功返回ok,看后台打印
hi,我叫:tian,22岁,性别:M这就是自定义的成功现实starter。
关键词:开箱即用,减少大量配置项,约定大于配置。
总结
Spring Boot扫描项目在启动时所依赖的项目JAR包,寻找包spring.factories文件的JAR包, 然后读取spring.factories自动配置类文件获取配置AutoConfiguration`, 然后自动配置类下满足条件(@ConditionalOnXxx)的@Bean放入到Spring容器中(Spring Context) 这样,用户就可以直接注入,因为这种类型已经在容器中了。本文转载自微信公众号「Java后端技术全栈」,请联系以下二维码。Java后端技术全栈微信官方账号。