当前位置: 首页 > 科技观察

徒手在SpringBoot里搓个starter,解密自动配置

时间:2023-03-20 02:26:59 科技观察

starter后台SpringBoot现在已经成为后端开发的必备技能之一,主要原因之一就是Spring有一个很重要的机制引导(启动机制)。启动器可以摒弃之前复杂的配置,集成到启动器中。使用时只需要在maven中引入相应的starter依赖,SpringBoot会自动扫描需要加载的信息并启动相应的默认配置。启动器将我们从处理各种依赖库和各种配置信息的烦恼中解脱出来。SpringBoot会自动通过classpath路径下的类发现需要的bean,并注册到IOC容器中。SpringBoot为日常企业应用开发的各种场景提供了spring-boot-starter依赖模块。所有这些依赖模块都遵循约定的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。我们经常看到或使用各种xxx-starters。比如下面的:SpringBootstarter的原理一般来说,无非就是将Jar包作为项目依赖引入到项目中。之所以现在比较难,是因为我们是在引入SpringBootStarter,所以我们需要了解一下SpringBoot是如何加载SpringBootStarter的Jar包的?下面我简单说一下。SpringBoot启动时会在依赖的启动包中寻找/META-INF/spring.factories文件,然后根据文件中配置的Jar包扫描项目依赖的Jar包,类似于Java的SPI机制.具体来说,可以使用@Conditional系列注解来实现更加精准的加载bean的配置条件。JavaSPI实际上是一种“基于接口编程+策略模式+配置文件”组合实现的动态加载机制。自定义starter的条件如果要自定义Starter,首先需要实现自动配置,要实现自动配置,需要满足以下两个条件:能够自动配置项目需要的配置信息,即自动加载依赖环境;能够根据项目提供的信息自动生成bean并注册到Bean管理容器中;实现自定义启动器org.springframework.bootspring-boot-autoconfigure2.0.0.RELEASE<依赖项org.springframework.bootspring-boot-configuration-processor2.0.0。RELEASEtrue根据需要自定义Starter的实现过程大致如下(以我定义的Starter为例):定义XxxPropertiesclass,属性配置类,完成属性配置相关的操作,比如设置属性前缀,在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,mynameis:"+properties.getName()+",今年"+properties.getAge()+"year"+",gender:"+properties.getSex());}}定义了XxxConfigurationProperties类,自动配置类,用于完成Bean的创建等工作。TianServiceAutoConfiguration代码:@Configuration@EnableConfigurationProperties(TianProperties.class)@ConditionalOnClass(TianService.class)@ConditionalOnProperty(prefix="spring.tian",value="enabled",matchIfMissing=true)publicclassTianServiceAutoConfiguration{@AutowiredprivateTianPropertiesproperties;@OnMissingalTianService.class)publicTianServicetianService(){returnnewTianService(properties);}}在resources下创建目录META-INF,在META-INF目录下创建spring.factories,SpringBoot启动时根据这个文件加载项目的自动配置类。"Configurationinspring.factories"org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.tian.TianServiceAutoConfiguration将上面的starter工程打成jar包:使用自定义starter创建一个SpringBoot工程测试。整体工程如下:在工程中添加自定义starter到pom依赖com.tianspring-boot-tian-starter1.0-SNAPSHOTTestApplication启动类@SpringBootApplication@EnableEurekaServerpublicclassTestApplication{publicstaticvoidmain(String[]args){SpringApplication.run(TestApplication.class,args);}}配置spring.tian.name=tianspring.tian.age=22spring.tian.sexinapplication.properties=M写一个TestController.java类RestController@RequestMapping("/my")publicclassTestController{@ResourceprivateTianServicetianService;@PostMapping("/starter")publicObjectstarter(){tianService.sayHello();return"ok";}}把我们定义的starter的jar依赖进来后,可以看到多了一个json文件。最后启动项目,输入http://localhost:9091/my/startercontroller成功返回ok,然后看后台打印hi,我叫:tian,今年22岁,性别:男,自定义starter已经成功实现。关键词:开箱即用,减少大量配置项,约定大于配置。总结SpringBoot在启动时会扫描项目所依赖的JAR包,寻找包含spring.factories文件的JAR包,然后读取spring.factories文件获取配置的自动配置类AutoConfiguration`,然后自动配置该类将满足条件(@ConditionalOnXxx)的@Bean打入Spring容器(SpringContext)中,这样用户就可以直接使用它进行注入,因为类已经在容器中了。本文转载自微信公众号《Java后端技术全栈》,可通过以下二维码关注。转载本文请联系Java后端技术全栈公众号。