springboot starter 原理解析及实践
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot starter 原理解析及实践相关的知识,希望对你有一定的参考价值。
参考技术Astarter是springBoot的一个重要部分。通过starter,我们能够快速的引入一个功能,而无需额外的配置。同时starter一般还会给我提供预留的自定配置选项,我们只需要在application.properties中设置相关参数,就可以实现配置的个性化。
那么这些方便的操作是怎么实现的呢?通过了解其原理,我们也可以做一个自己的starter,来让别人快速使用我们的功能。
按个人理解,我认为springBoot Starter就是一个 智能化的配置类 @Configuration 。
接下来介绍内容包括:
1、【创建module】,首先我们自定义一个starter的module,根据你的starter实现复杂度,引入相关spring组件。最基本的,我们只需引入 spring-boot-autoconfigure 模块。
2、【业务bean实现】实现我们的业务bean,案例中我们实现最简单的sayHello服务,输入msg,返回“hello,msg”。
3、然后就是Configuration类的创建,这个类是starter自动初始化的核心类,负责把业务相关的bean智能的加载进来。
4、配置 spring.factories ,通过该配置,才能让springboot来自动加载我们的Configuration类。具体原理我们稍后深入了解。
具体的,是在模块的 resources/META-INF 目录下,新建 spring.factories 文件。内容如下:
最后我们把上述模块单独执行以下install或者deploy,一个starter就做好了。
其他项目使用我们的starter就非常简单了:(1)引入starter依赖;(2)注入需要的service。
done!
回头再看上边的开发流程,有两个地方需要我们了解一下:
(1)如何让starter被自动识别加载:spring.factories里的EnableAutoConfiguration原理。
(2)如何实现自动加载的智能化、可配置化:@Configuration配置类里注解。
这里我们只简单的说一下大致的原理和流程,执行细节大家可以按照文章给出的思路自己去研读。
在SpringBoot的启动类,我们都会加上 @SpringBootApplication 注解。这个注解默认会引入 @EnableAutoConfiguration 注解。然后 @EnableAutoConfiguration 会 @Import(AutoConfigurationImportSelector.class) 。
AutoConfigurationImportSelector.class 的selectImports方法最终会通过 SpringFactoriesLoader.loadFactoryNames ,加载 META-INF/spring.factories 里的 EnableAutoConfiguration 配置值,也就是我们上文中设置的资源文件。
实际使用中,我们并不总是希望使用默认配置。比如有时候我想自己配置相关功能,有时候我想更改一下默认的服务参数。这些常见的场景Starter都想到了,并提供了如下的解决方案:
springboot starter提供了一系列的 @Conditional* 注解,代表什么时候启用对应的配置,具体的可以去查看一下springboot的官方文档。
比如我们案例中的 「@ConditionalOnClass(DemoHelloService.class)」,代表如果存在DemoHelloService类时,配置类才会生效;又比如「@ConditionalOnMissingBean(DemoHelloService.class)」,代表着如果项目中没有DemoHelloService类型的bean,那么该配置类会自动创建出starter默认的DemoHelloService类型bean。
这个注解主要是为了解决如下场景:我想要使用starter的默认配置类,但是又想对配置中的某些参数进行自定义配置。 @ConfigurationProperties 类就是做这个工作的。例如上述例子中,我想对默认的defaultMsg做些个性化的设置。就可以按如下方式来实现:
starter新增ConfigurationProperties类bean
启用property
在实际项目中自定义默认msg
深入springboot原理——动手封装一个starter
从上一篇文章《深入springboot原理——一步步分析springboot启动机制(starter机制)》
我们已经知道springboot的起步依赖与自动配置的机制。spring-boot-starter-xxx是官方提供的starter,xxx-spring-boot-starter是第三方提供的starter。starter.jar提供jar引入,autoconfigure.jar实现自动配置。下面我们就来封装一个自己的starter。
准备要封装的组件
新建组件com-itpsc-service,组件只有一个service。
pom文件
<groupId>com.itpsc</groupId> <artifactId>com-itpsc-service</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>com-itpsc-service</name> <description>com-itpsc-service</description>
编写UserService类
public class UserService { private String username; private String password; public void print() { System.out.println("username="+username + " password="+password); } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
打包发布组件
idea终端里面输入命令mvn install package打包到maven仓库。
新建一个starter
新建一个名称为itpsc-spring-boot-starter启动组件
引入spring-boot-starter、spring-boot-autoconfigure、spring-boot-configuration-processor
这些Jar在编写自动配置类、注解、生成配置元数据处理等功能依赖的jar包。
<groupId>com.itpsc.spring.boot</groupId> <artifactId>itpsc-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>2.0.4.RELEASE</version> </dependency> <dependency> <groupId>com.itpsc</groupId> <artifactId>com.itpsc.service</artifactId> </dependency> </dependencies
编写自动配置类
UserProperties.java,使用@ConfigurationProperties注解将配置文件(yml/properties)中指定前缀的配置转为bean。
package com.itpsc.spring.boot.starter; ... @ConfigurationProperties(prefix = "com.itpsc") public class UserProperties { private String username; private String password; ... }
UserAutoConfiguration.java,@Configuration 注释使类成为bean的工厂。
@EnableConfigurationProperties注解使@ConfigurationProperties注解生效。
package com.itpsc.spring.boot.starter; ... @Configuration @EnableConfigurationProperties(UserProperties.class) public class UserAutoConfiguration { @Bean public UserService getBean(UserProperties userProperties) { //创建组件实例 UserService userService = new UserService(); userService.setUsername(userProperties.getUsername()); userService.setPassword(userProperties.getPassword()); return userService; } }
配置spring.factories文件
\\META-INF\\spring.factories该文件用来定义需要自动配置的类,springboot启动时会进行对象的实例化,会通过加载类SpringFactoriesLoader加载该配置文件,将文件中的配置类加载到spring容器。
在src/main/resources新建META-INF文件夹,在META-INF文件夹下新建spring.factories文件。配置内容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\
com.itpsc.spring.boot.starter.UserAutoConfiguration
打包发布starter
idea终端里面输入命令mvn install package打包到maven仓库。
测试starter
我们在springboot-mybatis-demo项目中引入starter
<dependency> <groupId>com.itpsc.spring.boot</groupId> <artifactId>itpsc-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
当在yml中配置username、password时就可以看到有自动提示了,这是因为引入的jar中包含了元数据文件,详细见下文。
com:
itpsc:
username: "itpsc"
password: itpsc@123
元数据文件是在编译器通过处理所有被@ConfigurationProperties注解的节点来自动生成的。
测试在增加一个测试方法
@Autowired private UserService userService; @Test public void testItpscStarter() { userService.print(); }
运行结果:
2019-01-23 20:22:41.615 INFO 17184 --- [ main] .i.SpringbootMybatisDemoApplicationTests : Started SpringbootMybatisDemoApplicationTests in 11.505 seconds (JVM running for 14.582) username=itpsc password=itpsc@123
从运行结果可以看出,我们封装的starter中的jar包的bean已经完成了自动配置,说明我们的starter封装成功了。下面补充下上文提到的元数据相关知识。
元数据
springboot jar包含元数据文件,提供所有支持的配置属性的详细信息。这些文件旨在允许IDE开发人员在用户使用application.properties 或application.yml文件时提供上下文帮助和自动补全 。
主要的元数据文件是在编译器通过处理所有被@ConfigurationProperties注解的节点来自动生成的。
配置元数据位于jar文件中的META-INF/spring-configuration-metadata.json,它们使用一个具有”groups”或”properties”分类节点的简单JSON格式。
{ "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties", "defaultValue": 8080, "name": "server.port", "description": "Server HTTP port.", "type": "java.lang.Integer" }, { "defaultValue": "\\/", "deprecated": true, "name": "server.servlet-path", "description": "Path of the main dispatcher servlet.", "type": "java.lang.String", "deprecation": { "level": "error", "replacement": "server.servlet.path" }
这两个json节点server.port、server.servlet-path对应可以在yml或者properties文件中定义
server:
port: 8081
context-path: /
如果不知道spring是否支持某个配置的话,可以查看元数据文件看是否有对应的节点。
以上是关于springboot starter 原理解析及实践的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot:SpringBoot 的底层运行原理解析
SpringBoot 高级 原理分析 -- 自定义redis-starter