SpringBoot3.x入门到精通系列:2.1 自动配置原理
SpringBoot 3.x 自动配置原理
🎯 什么是自动配置
自动配置是SpringBoot的核心特性之一,它能够根据类路径中的依赖自动配置Spring应用。这使得开发者可以快速启动项目,而无需编写大量的配置代码。
核心理念
- 约定优于配置 (Convention over Configuration)
- 智能默认值 (Sensible Defaults)
- 条件化配置 (Conditional Configuration)
- 可覆盖性 (Overridable)
🔍 自动配置工作原理
1. 启动流程
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
@SpringBootApplication
注解包含三个关键注解:
@SpringBootConfiguration // 标识配置类
@EnableAutoConfiguration // 启用自动配置
@ComponentScan // 启用组件扫描
2. @EnableAutoConfiguration详解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {// 排除特定的自动配置类Class<?>[] exclude() default {};// 排除特定的自动配置类名String[] excludeName() default {};
}
3. AutoConfigurationImportSelector
这是自动配置的核心类,负责选择需要导入的自动配置类:
public class AutoConfigurationImportSelector implements DeferredImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}// 获取自动配置的元数据AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}// 获取注解属性AnnotationAttributes attributes = getAttributes(annotationMetadata);// 获取候选配置类List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 去重configurations = removeDuplicates(configurations);// 排除指定的配置类Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);// 过滤配置类configurations = getConfigurationClassFilter().filter(configurations);return new AutoConfigurationEntry(configurations, exclusions);}
}
📋 spring.factories文件
自动配置类的发现机制依赖于 META-INF/spring.factories
文件:
# Auto Configure
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.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration
🔧 条件注解详解
SpringBoot使用条件注解来决定是否应用某个自动配置:
1. 常用条件注解
注解 | 作用 | 示例 |
---|---|---|
@ConditionalOnClass | 类路径存在指定类时生效 | @ConditionalOnClass(DataSource.class) |
@ConditionalOnMissingClass | 类路径不存在指定类时生效 | @ConditionalOnMissingClass("com.example.SomeClass") |
@ConditionalOnBean | 容器中存在指定Bean时生效 | @ConditionalOnBean(DataSource.class) |
@ConditionalOnMissingBean | 容器中不存在指定Bean时生效 | @ConditionalOnMissingBean(DataSource.class) |
@ConditionalOnProperty | 配置属性满足条件时生效 | @ConditionalOnProperty("spring.datasource.url") |
@ConditionalOnResource | 资源文件存在时生效 | @ConditionalOnResource("classpath:config.properties") |
@ConditionalOnWebApplication | Web应用时生效 | @ConditionalOnWebApplication |
@ConditionalOnNotWebApplication | 非Web应用时生效 | @ConditionalOnNotWebApplication |
2. 实际应用示例
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcTemplateAutoConfiguration {@Configuration(proxyBeanMethods = false)@ConditionalOnMissingBean(JdbcOperations.class)static class JdbcTemplateConfiguration {@Bean@PrimaryJdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);JdbcProperties.Template template = properties.getTemplate();jdbcTemplate.setFetchSize(template.getFetchSize());jdbcTemplate.setMaxRows(template.getMaxRows());if (template.getQueryTimeout() != null) {jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());}return jdbcTemplate;}}
}
🛠️ 自定义自动配置
1. 创建自动配置类
package com.example.autoconfigure;import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;@AutoConfiguration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyServiceProperties.class)
@ConditionalOnProperty(prefix = "myservice", name = "enabled", havingValue = "true", matchIfMissing = true)
public class MyServiceAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic MyService myService(MyServiceProperties properties) {return new MyService(properties.getName(), properties.getTimeout());}
}
2. 创建配置属性类
package com.example.autoconfigure;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "myservice")
public class MyServiceProperties {/*** 是否启用MyService*/private boolean enabled = true;/*** 服务名称*/private String name = "default-service";/*** 超时时间(毫秒)*/private int timeout = 5000;// Getter和Setter方法public boolean isEnabled() { return enabled; }public void setEnabled(boolean enabled) { this.enabled = enabled; }public String getName() { return name; }public void setName(String name) { this.name = name; }public int getTimeout() { return timeout; }public void setTimeout(int timeout) { this.timeout = timeout; }
}
3. 创建服务类
package com.example.autoconfigure;public class MyService {private final String name;private final int timeout;public MyService(String name, int timeout) {this.name = name;this.timeout = timeout;}public String doSomething() {return "MyService[" + name + "] executed with timeout: " + timeout + "ms";}public String getName() { return name; }public int getTimeout() { return timeout; }
}
4. 注册自动配置
在 src/main/resources/META-INF/spring.factories
中注册:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfigure.MyServiceAutoConfiguration
或者在SpringBoot 2.7+中,使用 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
:
com.example.autoconfigure.MyServiceAutoConfiguration
5. 使用自动配置
在应用中直接注入使用:
@RestController
public class TestController {private final MyService myService;public TestController(MyService myService) {this.myService = myService;}@GetMapping("/test")public String test() {return myService.doSomething();}
}
配置文件:
myservice:enabled: truename: custom-servicetimeout: 10000
🔍 调试自动配置
1. 启用自动配置报告
# 启用自动配置调试信息
debug=true# 或者通过日志级别
logging.level.org.springframework.boot.autoconfigure=DEBUG
2. 查看自动配置报告
启动应用后,控制台会输出详细的自动配置报告:
============================
CONDITIONS EVALUATION REPORT
============================Positive matches:
-----------------AopAutoConfiguration matched:- @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)AopAutoConfiguration.ClassProxyingConfiguration matched:- @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)- @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)Negative matches:
-----------------ActiveMQAutoConfiguration:Did not match:- @ConditionalOnClass did not find required class 'jakarta.jms.ConnectionFactory' (OnClassCondition)AopAutoConfiguration.AspectJAutoProxyingConfiguration:Did not match:- @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice' (OnClassCondition)
3. 使用Actuator查看自动配置
添加依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置:
management:endpoints:web:exposure:include: conditions
访问端点:http://localhost:8080/actuator/conditions
📊 自动配置最佳实践
1. 配置类设计原则
- 使用
@AutoConfiguration
而不是@Configuration
- 合理使用条件注解
- 提供合理的默认值
- 支持配置覆盖
2. 性能优化
@AutoConfiguration
@ConditionalOnClass(SomeClass.class)
@EnableConfigurationProperties(SomeProperties.class)
public class SomeAutoConfiguration {// 使用 proxyBeanMethods = false 提高性能@Configuration(proxyBeanMethods = false)static class SomeConfiguration {@Bean@ConditionalOnMissingBeanpublic SomeService someService() {return new SomeService();}}
}
3. 排除自动配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class
})
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
或通过配置文件:
spring:autoconfigure:exclude:- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration- org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
🔗 下一篇
在下一篇文章中,我们将深入学习SpringBoot的依赖注入与IoC容器,了解Spring的核心机制。
本文关键词: 自动配置, EnableAutoConfiguration, 条件注解, spring.factories, 自定义配置