springboot 1.5.3 源码分析(二):springboot自动化配置原理及自定义starter
来源:互联网 发布:iphone7plus无移动数据 编辑:程序博客网 时间:2024/04/25 08:41
前面的文章已经讲了springboot的实现原理,无非就是通过spring的condition条件实现的,还是比较简单的(感谢spring设计的开放性与扩展性)。
在实际工作过程中会遇到需要自定义starter的需求,那么我们接下来就自己实现一个starter。
先看一下目录结构:
MyConfig
是自定义的配置类HelloService
是自定义的beanHelloServiceProperties
是自定义的类型安全的属性配置MEYA-INF/spring.factories
文件是springboot的工厂配置文件
本项目就是自定义的starter。假设我们这里需要一些配置项,使用者在使用该starter时,需要在application.properties文件中配置相关属性。这里我们使用了@ConfigurationProperties
来将属性配置到一个POJO类中。这样做的好处是:可以检测数据的类型,并且可以对数据值进行校验,详情请参考我的另一篇博客:
HelloServiceProperties
类内容如下:
import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;/** * Created by hzliubenlong on 2017/12/13. */@Data@Component@ConfigurationProperties(prefix = "hello")public class HelloServiceProperties { private String a; private String b;}
这样使用这个starter的时候,就可以配置hello.a=**
来设置属性了。
HelloService
是我们的bean,这里实现比较简单,获取外部的属性配置,打印一下日志。内容如下:
/** * Created by hzliubenlong on 2017/12/12. */@Slf4jpublic class HelloService { String initVal; public void setInitVal(String initVal) { this.initVal = initVal; } public String getInitVal() { return initVal; } public String hello(String name) { log.info("initVal={}, name={}", initVal, name); return "hello " + name; }}
接下来是比较重要的配置类MyConfig
,前面已经讲过,springboot是通过条件注解来判断是否要加载bean的,这些内容都是在我们自定义的配置类中来实现:
import com.example.myservice.HelloService;import com.example.properties.HelloServiceProperties;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration@EnableConfigurationProperties(HelloServiceProperties.class)public class MyConfig { @Autowired private HelloServiceProperties helloServiceProperties; @ConditionalOnProperty(prefix="hello", value="enabled", matchIfMissing = true) @ConditionalOnClass(HelloService.class) @Bean public HelloService initHelloService() { HelloService helloService = new HelloService(); helloService.setInitVal(helloServiceProperties.getA()); return helloService; }}
@Configuration
表明这是一个配置类 @EnableConfigurationProperties(HelloServiceProperties.class)
表示该类使用了属性配置类HelloServiceProperties
initHelloService()
方法就是实际加载初始化helloService
bean的方法了,它上面有三个注解:
1. @ConditionalOnProperty(prefix="hello", value="enabled", matchIfMissing = true)
: hello.enabled=true
时才加载这个bean,配置没有的话,默认为true,也就是只要引入了这个依赖,不做任何配置,这个bean默认会加载。
2. @ConditionalOnClass(HelloService.class)
:当HelloService这个类存在时才加载bean。
3. @Bean
:表明这是一个产生bean的方法,改方法生成一个HelloService的bean,交给spring容器管理。
好了,到这里,我们的代码已经写完。根据前面讲的springboot的原理我们知道,springboot是通过扫描MEYA-INF/spring.factories
这个工厂配置文件来加载配置类的, 所以我们还需要创建这个文件。其内容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.example.demo.MyConfig
上面的\
是换行符,只是为了便于代码的阅读。通过这个文件,springboot就可以读取到我们自定义的配置类MyConfig。
接下来我们只需要打个jar包即可供另外一个项目使用了。下面贴一下pom.xml的内容:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>springboot-starter-hello</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-starter-hello</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-release-plugin</artifactId> <version>2.4.2</version> <dependencies> <dependency> <groupId>org.apache.maven.scm</groupId> <artifactId>maven-scm-provider-gitexe</artifactId> <version>1.8.1</version> </dependency> </dependencies> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> <configuration> <skip>false</skip> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.7</version> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> <manifest> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> </manifest> </archive> </configuration> </plugin> </plugins> </build></project>
上面定义了一个starter,下面我们将写一个新的工程,来引用我们自定义的starter。还是先看一下项目目录:
要想引用我们自定义的starter,自然是先引入依赖了:
<dependency> <groupId>com.example</groupId> <artifactId>springboot-starter-hello</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
然后再application.properties文件中添加如下配置:
hello.enabled=truehello.a=hahaha
好了,现在就可以在项目中注入HelloService
使用了。是的,就是那么简单.DemoApplication
主类如下:
import com.example.demo.environment.EnvironmentService;import com.example.myservice.HelloService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@Slf4j@SpringBootApplicationpublic class DemoApplication { @Autowired HelloService helloService; @RequestMapping("/") public String word(String name) { return helloService.hello(name); } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}
启动项目,访问URLhttp://127.0.0.1:8080/?name=hhh
:
后台打印日志为initVal=hahaha, name=hhh
其中hahaha
就是我们没在配置文件中配置的属性值,这句日志是我们上面starter项目中com.example.myservice.HelloService#hello
方法打印出来的。
end。
- springboot 1.5.3 源码分析(二):springboot自动化配置原理及自定义starter
- SpringBoot自动化配置原理
- springboot 1.5.3 源码分析(四):自定义Conditional注解
- springBoot(二)springboot配置读取、配置原理及其视图
- SpringBoot 配置分析(二)
- springboot入门(二)--springboot常用注解及配置
- SpringBoot | 异常配置源码分析
- SpringBoot内部的一些自动化配置原理
- springboot学习二(springboot相关配置)
- SpringBoot之starter(R)
- springboot源码分析2-springboot 之banner定制以及原理
- springboot源码分析5-springboot之命令行参数以及原理
- springboot 1.5.3 源码分析(五):@SpringBootApplication注解,springboot注解
- sbc(三)自定义Starter-SpringBoot重构去重插件
- springboot 1.5.3 源码分析(一):项目初始化过程
- springboot 1.5.3 源码分析(三):spring @Conditional注解
- springboot源码分析11-ApplicationContextInitializer原理
- springboot源码分析3-springboot之banner类架构以及原理
- 学习一下学习一下学习一下学习一下学习一下
- 小学生开始学Python,还有什么能够阻挡我对Python的向往?
- (PTA详解)L1-002. 打印沙漏
- 常用的sql 语句
- C# Process线程
- springboot 1.5.3 源码分析(二):springboot自动化配置原理及自定义starter
- lua语法2
- C++操作MySQL
- g++ 编译参数
- VS测试程序运行时间
- ZookeeperClient(基于ZooKeeperNetEx再次封装)
- SSL/TLS协议运行机制的概述
- mmap(内存影射)和shm(共享存储)
- Effective Java之避免使用终结方法(七)