在第一篇文章介绍Spring Boot启动过程,提到了Spring Boot的核心能力 - 自动配置。这个能力也是Spring Boot非常大的卖点之一。对这个能力,相信很多同学都会比较好奇,Spring Boot是如何实现它的呢?
但是在详细探究Spring Boot是如何实现自动配置之前,首先需要明确问题的来源是什么,以及了解目前Spring框架中提供的相关能力。
引子
问题是什么
Spring中纷繁复杂的配置文件一直让广大开发人员颇有微词,但是随着业务的复杂度越来越高,这也是在所难免的事情。
哪怕是要创建一个简单的Web应用,需要配置的东西也是一坨坨的,这个过程虽然不复杂但是很繁琐,而且非常容易出错。所以聪明的开发人员想出了很多办法来解决这个问题,比如Maven的Archetype创建,又或者各个公司内部的脚手架小工具。但是这些方案总是有这样那样的问题,比如维护不方便,不好定制等等。
在云计算,弹性计算以及微服务越来越普及的今天,急需要一种自动配置的方式,从而方便地按需部署。所以Spring Boot应用而生,而自动配置作为Spring Boot的闪光点之一,自然非常受人关注。
Spring Boot的自动配置功能,其实从本质上说并没有引入什么新功能,它只是将Spring现存的能力做了一次组合和封装。那么在深入了解Spring Boot的自动配置原理之前,可以先了解一下Spring的这些已知能力,打下良好地基础。
和配置相关的Spring已有能力
@Profile
很多时候,我们开发的Spring应用,需要根据所在环境的不同注册相应的Bean到上下文中。
比如本地开发环境中,数据库连接对象往往指向的是开发数据库;在测试环境中,又会指向测试数据库;而到了线上,指向的自然是生产数据库。
为了满足这个常见需求,Spring 3.1中引入了Profile的概念。比如在下面的代码中,配置类会根据所在环境(Profile)的不同,向上下文中注入对应的Bean实例。
@Configuration
public class DataSourceConfiguration
{
@Bean
@Profile("DEV")
public DataSource devDataSource() {
// ...
}
@Bean
@Profile("TEST")
public DataSource testDataSource() {
// ...
}
@Bean
@Profile("PROD")
public DataSource prodDataSource() {
// ...
}
}
那么,如何声明应用所处的Profile呢?还是有几种选择:
- 配置文件,比如在application.properties中声明
spring.profiles.active=DEV
- 启动参数,比如
-Dspring.profiles.active=DEV
这个Profile的概念很直观,但是由于它仅仅是依赖一个字符串的值作出决策,所以不够灵活和强大。因此就有了下面@Conditional注解和Condition接口的诞生。
@Conditional以及Condition接口
它们是Spring 4中引入的新功能。
Condition接口和@Conditional接口通常会一起配合使用。
Condition接口的定义如下: