Spring Boot 自动配置机制原理解析与实战应用
Spring Boot自动配置的底层实现机制
Spring Boot框架的自动装配能力由@EnableAutoConfiguration注解触发。深入探索该注解的源码实现,可以发现其核心依赖于一个关键的工厂加载方法:
org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(Class<?>, ClassLoader)
该方法的实现逻辑如下:
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
// 定位所有包含spring.factories文件的资源位置
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
classLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
// 加载每个文件中的配置属性
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
// 解析逗号分隔的类名列表
result.addAll(Arrays.asList(
StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
} catch (IOException ex) {
throw new IllegalArgumentException("无法从[" + FACTORIES_RESOURCE_LOCATION +
"]位置加载[" + factoryClass.getName() + "]工厂类", ex);
}
}
该方法会扫描整个类路径下所有JAR包中特定位置的配置文件:
/**
* 工厂配置文件的存储位置
* <p>该文件可能在多个JAR包中存在</p>
*/
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
在Spring Boot的自动配置模块(例如spring-boot-autoconfigure-1.5.6.RELEASE.jar)中,我们可以找到这个配置文件,其中定义了大量的自动配置类:
# 自动配置类注册表
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
...
以数据源自动配置的实现为例,其关键注解结构为:
@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class})
public class DataSourceAutoConfiguration {
// 配置实现细节
}
这里体现了自动配置的两个核心要素:@Configuration表明这是一个配置类,@ConditionalOnClass则根据类路径中是否存在特定类来决定是否激活该配置。
实现自定义的自动配置模块
掌握了自动配置的基本原理后,我们可以创建自己的自动配置功能。下面是一个完整的实现示例:
第一步:构建配置功能类
public class ConfigurationReader implements EnvironmentAware {
private final Logger log = LoggerFactory.getLogger(getClass());
private Environment environment;
public String readString(String propertyKey) {
return environment.getProperty(propertyKey);
}
public Long readLong(String propertyKey) {
String value = readString(propertyKey);
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
log.warn("数值转换异常,键值对: {} = {}", propertyKey, value);
return 0L;
}
}
public Integer readInteger(String propertyKey) {
return readLong(propertyKey).intValue();
}
@Override
public void setEnvironment(Environment env) {
this.environment = env;
}
}
第二步:创建自动配置类
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.PropertyResolver;
@Configuration
@ConditionalOnClass(PropertyResolver.class)
public class ConfigurationReaderAutoConfig {
@Bean
public ConfigurationReader configurationReader() {
return new ConfigurationReader();
}
}
第三步:注册自动配置
在项目资源目录创建META-INF/spring.factories文件,添加配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.config.ConfigurationReaderAutoConfig
完成以上三步,自定义的自动配置模块即可生效。
查看自动配置状态信息
了解哪些自动配置类被加载或排除,有多种方式可以查看详细报告:
- Maven插件方式:使用
spring-boot:run时在环境变量中添加debug=true - JAR运行方式:执行命令时添加
--debug参数 - IDE配置方式:在虚拟机参数中添加
-Ddebug - 配置文件方式:在
application.properties或application.yml中设置debug: true - 监控端点方式:集成Actuator后访问
/actuator/conditions端点
应用启动时将显示详细的自动配置报告:
=========================
自动配置分析报告
=========================
已激活的配置:
-------------
AopAutoConfiguration 已激活:
- 检测到必需的类: 'org.springframework.context.annotation.EnableAspectJAutoProxy',
'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (类条件检查)
- 属性条件 spring.aop.auto=true 匹配成功 (属性条件检查)
...
ConfigurationReaderAutoConfig 已激活:
- 检测到必需的类: 'org.springframework.core.env.PropertyResolver' (类条件检查)
ErrorMvcAutoConfiguration 已激活:
- 检测到必需的类: 'javax.servlet.Servlet', 'org.springframework.web.servlet.DispatcherServlet'
(类条件检查)
- 检测到Web应用环境: StandardServletEnvironment (Web应用条件检查)
未激活的配置:
-------------
ActiveMQAutoConfiguration:
未激活原因:
- 未找到必需的类: 'javax.jms.ConnectionFactory',
'org.apache.activemq.ActiveMQConnectionFactory' (类条件检查)
BatchAutoConfiguration:
未激活原因:
- 未找到必需的类: 'org.springframework.batch.core.launch.JobLauncher' (类条件检查)
...
报告明确分为两部分:
- 已激活的配置:满足所有条件并成功加载的自动配置类
- 未激活的配置:因某些条件不满足而被跳过的自动配置类
从输出中可以看到,我们自定义的ConfigurationReaderAutoConfig已被成功识别并启用。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 只有那年胜过年年!
评论
