当前位置: 首页 > news >正文

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")
@ConditionalOnWebApplicationWeb应用时生效@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, 自定义配置

http://www.dtcms.com/a/310889.html

相关文章:

  • 【软考中级网络工程师】知识点之 VRRP
  • 关于Web前端安全防御CSRF攻防的几点考虑
  • 关于人工智能AI>ML>DL>transformer及NLP的关系
  • MySQL(173)MySQL中的存储过程和函数有什么区别?
  • 【DeepSeek-R1 】分词系统架构解析
  • 快速了解决策树
  • API征服者:Python抓取星链卫星实时轨迹
  • Docker 部署与配置 MySQL 5.7
  • 四、Portainer图形化管理实战与Docker镜像原理
  • 2024年网络安全案例
  • 从数据丢失到动画流畅:React状态同步与远程数据加载全解析
  • Jotai:React轻量级原子化状态管理,告别重渲染困扰
  • 《深潜React列表渲染:调和算法与虚拟DOM Diff的优化深解》
  • 《React+TypeScript实战:前端状态管理的安全架构与性能优化深解》
  • Oracle 11g RAC集群部署手册(三)
  • SQL 四大语言分类详解:DDL、DML、DCL、DQL
  • Oracle 11g RAC集群部署手册(一)
  • 探索:Uniapp 安卓热更新
  • flink写paimon表的过程解析
  • cmd怎么取消关机命令
  • 【DL学习笔记】yaml、json、随机种子、浮点精度、amp
  • hcip---ospf知识点总结及实验配置
  • 学习嵌入式第十八天
  • rag学习-以项目为基础快速启动掌握rag
  • 深入 Go 底层原理(十):defer 的实现与性能开销
  • Vue3+ts自定义指令
  • 深入 Go 底层原理(二):Channel 的实现剖析
  • 基于结构熵权-云模型的铸铁浴缸生产工艺安全评价
  • 打靶日记-RCE-labs(续)
  • linux eval命令的使用方法介绍