如何编写Spring-Boot自动配置
摘要
本文主要介绍如何把一个spring的项目(特别是一些公共工具类项目),基于spring boot的自动配置的思想封装起来,使其他Spring-Boot项目引入后能够进行快速配置。
AutoConfiguration
Spring-boot的一个重要特性就是提供了各种各样的AutoConfiguration。例如DataSourceAutoConfiguration。这样我们只需要在配置文件中进行如下配置
spring:
datasource:
url: jdbc:mysql://xxxxxxxxxxx/realname
username: xxxxx
password: xxxxx
driverClassName: com.mysql.jdbc.Driver
Spring-Boot就会在容器中按照我们的配置的信息注入一个DataSource。那么Spring boot是怎么知道 DataSourceAutoConfiguration是自动配置类?其实很简单:
- spring boot 在启动时候会读取文件Classpath:\META-INF\spring.factories的所有文件,spring.factories其实是一个properties的文件,即是 key = value的形式。
- 获取spring.factories中key=org.springframework.boot.autoconfigure.EnableAutoConfiguration配置项的值(类的全路径)作为Spring启动配置类
Spring Boot 这种用“约定优于配置”思想可以大大的简化配置代码的编写。那么,我们就可以按照上面的套路来编写一个Spring-Boot的自动配置类吧
实战
现在有一个配置Bean——PrintAfterInitBean,需要Spring容器启动以后,打印一次消息,并且该消息的内容是在配置文件中定义
第一步,编写配置Bean——PrintAfterInitBean
代码如下,因为只是一个简单例子,这里的配置Bean其实可以是其他任何复杂配置Bean,例如DataSource。往往一个公共包需要多个这样配置Bean才能完成其配置。
public class PrintAfterInitBean implements InitializingBean {
private String message;
public void afterPropertiesSet() throws Exception {
System.out.println(message);
}
//setter getter
}
第二步,创建一个AutoConfiguration。
如果搜索Spring Boot下面的类,你会发现其实有很多名字形如xxxAutoConfiguration的类,这些类都是Spirng Boot为我们做的一些快捷配置类。 创建一个TestAutoConfig,作为一个自动配置类
@Configuration
public class TestAutoConfig { @Bean
@ConfigurationProperties(prefix = "init")
@ConditionalOnMissingBean(PrintAfterInitBean.class)
@ConditionalOnProperty(prefix = "init",value = "message")
public PrintAfterInitBean printAfterInitBean() {
return new PrintAfterInitBean();
}
}
- @ConfigurationProperties 是Spring Boot提供的方便属性注入的注解,功能其实和@Value类似
- @ConditionalOnMissingBean 表示当BeanFactory中没有PrintAfterInitBean类型的Bean才会创建,否则就会忽略这个Bean。这个就是上图中所谓的【满足自动配置条件】,同理的,ConditionalOnProperty表示当存在配置前缀为init,配置值为message的配置的时候,才会生效。@ConditionalOnXXX 系列的注解都是为了在自动配置中,不侵入用户的配置。
第三步,创建spring.factories
在resources下面创建META-INF/spring.factories, 然后在文件中把第二步的类配置进去
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.netease.xxx.xxx.UrsPropertyAutoConfig
这样就完成一个Spring Boot自动配置,如果存在init.message的配置,那么spring boot启动的时候就会打印init.message配置对应值。
小结
Spring Boot的自动配置为我们在编写一个重复的配置代码(或者xml文件)中提供一套简便的部署方式,这样当用其他spring boot的项目依赖我们jar时候,配置起来就十分方便拉。从代码可以看出,Spring Boot 其实并没有什么实质性的创新,只是把一些“约定”的配置信息转换原来通过代码或xml实现的配置。
常用注解
@ConditionalOnXXX
前面已经介绍过,@ConditionalOnXXX 系列主要是自动配置是否生效,例如ConditionalOnClass,就是在某个Class存在的情况下才生效。这一系列的注解通过名字就知道用法,因此不再做过多的介绍。@ConditionalOnXXX 可以用于类名和方法名上。
- 用于类名上,要和 @Configuration一起使用,决定该配置类是否生效
- 用于方法名上(注:前提是该方法也是一个配置类,即有@Configuration注解),结合@Bean一起使用,判断该@Bean是否生成
用DataSourceAutoConfiguration 代码来说明,
@Configuration
// 注:当存在DataSource.class 和 EmbeddedDatabaseType.class 存在的情况下,该配置路径才生效
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration { private static final Log logger = LogFactory
.getLog(DataSourceAutoConfiguration.class); @Bean
// 注:只有当BeanFactory中不存在DataSourceInitializer类的Bean的情况下才会有效
@ConditionalOnMissingBean
public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties,
ApplicationContext applicationContext) {
return new DataSourceInitializer(properties, applicationContext);
}
...
}
自动配置的核心思想就是不侵占用户的代码,类似于“你有就用你的,你没有我就帮你做默认设置”。因此,我们在自己开发一个自动配置类的时候也需要注意这一点,不然就有点霸王条款的感觉
@EnableConfigurationProperties
一般我们的自动配置类都会依赖外部的配置信息,而这些外部的配置信息可以封装成一个类,类似上面DataSourceAutoConfiguration中的@EnableConfigurationProperties(DataSourceProperties.class),DataSourceProperties类就是用来保存DataSource相关的配置信息。“约定优于配置”的思想就在这里体现,如果配置信息是以spring.datasource为前缀,那么配置信息都会注入到DataSourceProperties类中,供DataSourceAutoConfiguration使用。
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
implements BeanClassLoaderAware, EnvironmentAware, InitializingBean { ...
private Class<? extends DataSource> type;
private String driverClassName;
private String url;
private String username;
private String password;
...
@AutoConfigureAfter
在一些特殊的情况下,一些自动配置类需要在某一些其他配置类后进行,例如依赖另外一个自动配置的Bean,这个时候就@AutoConfigureAfter来进行约束。
@Import
@Import也是比较常见的一个配置注解,主要用于引入其他配置类,但是另外一个比较有用的配置就是引入一个ImportBeanDefinitionRegistrar接口,而这个就是用于使用在ApplicationContext初始化阶段的时候,注册(register)一些BeanDefinition。当然常见的Bean是可以通过@Bean注解注入,但是一些Spring ApplicationContext启动过程中用的到一些Bean则不行,例如BeanPostProcessor,BeanFactoryPostProcessor。
总结
Spring Boot 核心思想就是“约定优于配置”思想,在创建一个微服务的时候有很多得天独厚的优势,往往只用短短几行配置,就可以部署一个应用。这样在编码更多的是一些业务层面。而如果我们自己编写的一个公共包也能够通过短短几行配置即可以完成,不仅仅是代码层面的减少,更是接入方来说是一种“一站式服务”体验。当然前提是接入方也是使用的Spring Boot。
如何编写Spring-Boot自动配置的更多相关文章
- Springboot 系列(三)Spring Boot 自动配置原理
注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别. 前言 关于配置文件可以配置的内容,在 Spring ...
- Spring Boot自动配置与Spring 条件化配置
SpringBoot自动配置 SpringBoot的自动配置是一个运行时(应用程序启动时)的过程,简化开发时间,无需浪费时间讨论具体的Spring配置,只需考虑如何利用SpringBoot的自动配置即 ...
- Spring Boot自动配置原理与实践(一)
前言 Spring Boot众所周知是为了简化Spring的配置,省去XML的复杂化配置(虽然Spring官方推荐也使用Java配置)采用Java+Annotation方式配置.如下几个问题是我刚开始 ...
- Spring Boot自动配置原理(转)
第3章 Spring Boot自动配置原理 3.1 SpringBoot的核心组件模块 首先,我们来简单统计一下SpringBoot核心工程的源码java文件数量: 我们cd到spring-boot- ...
- Spring Boot 自动配置之@Conditional的使用
Spring Boot自动配置的"魔法"是如何实现的? 转自-https://sylvanassun.github.io/2018/01/08/2018-01-08-spring_ ...
- Spring Boot自动配置原理、实战
Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...
- Spring Boot自动配置
Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...
- Spring boot 自动配置自定义配置文件
示例如下: 1. 新建 Maven 项目 properties 2. pom.xml <project xmlns="http://maven.apache.org/POM/4 ...
- Spring Boot自动配置如何工作
通过使用Mongo和MySQL DB实现的示例,深入了解Spring Boot的@Conditional注释世界. 在我以前的文章“为什么选择Spring Boot?”中,我们讨论了如何创建Sprin ...
- Spring boot --- 自动配置
spring boot 自动配置 指的是针对很多spring 应用程序常见的应用功能,spring boot 能自动提供相关配置. spring boot 自动配置加载 Spring boot ...
随机推荐
- Omi全新版本来袭 - 指令系统
写在前面 Omi框架到目前为止有三种版本. omi.js 使用 sodajs 为内置指令系统 omi.lite.js 不包含任何模板引擎 omi.mustache.js 使用 mustache.js为 ...
- TomCat杀进程
有时候当你的tomcat启动时会发现 因为报以下的错误: "Several ports ( 8080, 8009) required by Tomcat v6.0 Server at loc ...
- [Linux] PHP程序员玩转Linux系列-telnet轻松使用邮箱
1.PHP程序员玩转Linux系列-怎么安装使用CentOS 2.PHP程序员玩转Linux系列-lnmp环境的搭建 3.PHP程序员玩转Linux系列-搭建FTP代码开发环境 4.PHP程序员玩转L ...
- STM8驱动HX711
普及:HX711AD一款专为高精度电子秤而设计的 24 位 A/D 转换器芯片: 获取数据方法:两个普通IO DOUT输入:GPIO_Mode_In_FL_N ...
- MySQL执行sql查询并上传至远程服务器
最近项目中有需要做一个shell脚本,可以对一个数据库执行sql操作,并将结果转为txt,筛选结果用tab隔开,保存至一个远程服务器上,以供其他人用Excel读取用txt中的内容. MySQL中将结果 ...
- JS设计模式之---单例模式
单例模式是保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式在现在面向对象的语言Java,C#,C++等等中也有很多用到,其实它在Javascript中使用同样非常广泛. var Cre ...
- (练习题)利用构造器函数实现三个小实例——不使用String()与Array()构造器和Math对象,不使用内建的方法的方法和属性。
1)在String()构造器不存在的情况下自定义一个myString()构造器函数.由于String()不存在,因此您在写构造器函数时不能使用任何属于内建String对象的方法和属性.并让你所创建的对 ...
- 大数据及hadoop相关知识介绍
一.大数据的基本概念 1.1什么是大数据 互联网企业是最早收集大数据的行业,最典型的代表就是Google和百度,这两个公司是做搜索引擎的,数量都非常庞大,每天都要去把互联网上的各种各样的网页信息抓取下 ...
- 蓝桥杯-马虎的算式-java
/* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...
- C#控制台程序使用Log4net日志组件
1.Log4net一般都不陌生,但是在配置上不同类型的项目又不相同的地方比如C#控制台程序和C# MVCWeb项目,拿控制台项目为例 项目源码在文章底部 2.首先创建一个控制台程序,引入Log4n ...