Spring Boot条件装配原理
Spring Boot条件装配原理引言条件装配是Spring Boot自动配置的核心机制通过Conditional及其派生注解Spring能够根据当前环境、classpath、配置属性等因素智能地决定是否创建某个Bean。本文将深入剖析条件装配的实现原理、各种条件注解的使用方法以及自定义条件注解的开发技巧。一、Conditional基础1.1 原始ConditionalTarget({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface Conditional { Class? extends Condition[] value(); } public interface Condition { boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }1.2 条件实现示例public class DatabaseCondition implements Condition { Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment env context.getEnvironment(); String dbType env.getProperty(app.database.type); return dbType ! null !dbType.isEmpty(); } } Configuration Conditional(DatabaseCondition.class) public class DatabaseConfiguration { // 条件满足时才加载 }二、Spring Boot条件注解2.1 常用条件注解ConditionalOnClass // classpath存在指定类时生效 ConditionalOnMissingClass // classpath不存在指定类时生效 ConditionalOnBean // 容器中存在指定Bean时生效 ConditionalOnMissingBean // 容器中不存在指定Bean时生效 ConditionalOnProperty // 配置属性满足条件时生效 ConditionalOnResource // 存在指定资源文件时生效 ConditionalOnWebApplication // 是Web应用时生效 ConditionalOnNotWebApplication // 非Web应用时生效 ConditionalOnExpression // SpEL表达式为true时生效 ConditionalOnJava // JDK版本满足条件时生效 ConditionalOnCloudPlatform // 指定云平台时生效2.2 组合条件Configuration ConditionalOnClass(DataSource.class) ConditionalOnProperty( prefix spring.datasource, name url ) EnableConfigurationProperties(DataSourceProperties.class) AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) public class DataSourceConfiguration { }三、ConditionalOnClass详解3.1 基本用法Configuration ConditionalOnClass({DataSource.class, JdbcTemplate.class}) public class JdbcTemplateConfiguration { Bean ConditionalOnMissingBean(JdbcTemplate.class) public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } }3.2 间接依赖检测// 自动检测DataSource的间接依赖 Configuration ConditionalOnClass(DataSource.class) // 会自动检测HikariDataSource等 public class DataSourcePoolConfiguration { }四、ConditionalOnProperty详解4.1 完整配置Configuration ConditionalOnProperty( prefix myapp.cache, name enabled, havingValue true, matchIfMissing false ) public class CacheConfiguration { } Configuration ConditionalOnProperty( prefix myapp.service, name {enabled, cache.enabled}, havingValue true, matchIfMissing true ) public class ServiceConfiguration { }4.2 松散绑定Configuration ConditionalOnProperty( prefix myapp.security, name sso-enabled // 支持 ssoEnabled, sso_enabled, SSO_ENABLED ) public class SsoConfiguration { }五、ConditionalOnBean详解5.1 Bean依赖条件Configuration public class CacheAutoConfiguration { Bean ConditionalOnBean(CacheManager.class) ConditionalOnMissingBean(name customCacheManager) public CacheManager customCacheManager() { return new ConcurrentMapCacheManager(); } }5.2 搜索策略Configuration ConditionalOnBean( value DataSource.class, search Search.LOCAL, // 只搜索当前容器 type com.zaxxer.hikari.HikariDataSource // 特定类型 ) public class HikariConfiguration { }六、自定义条件注解6.1 注解定义Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Conditional(OnRedisCondition.class) public interface ConditionalOnRedis { String value() default localhost; } public class OnRedisCondition implements Condition { Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { MapString, Object attrs metadata.getAnnotationAttributes( ConditionalOnRedis.class.getName()); String host (String) attrs.get(value); Environment env context.getEnvironment(); String redisHost env.getProperty(spring.redis.host, localhost); return redisHost.equals(host); } }6.2 复合条件Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Conditional({ OnRedisCondition.class, OnCacheEnabledCondition.class }) public interface ConditionalOnRedisCache { }七、条件装配顺序7.1 AutoConfigureOrderConfiguration AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) ConditionalOnClass(DataSource.class) public class DataSourceAutoConfiguration { }7.2 AutoConfigureAfterConfiguration AutoConfigureAfter(DataSourceAutoConfiguration.class) ConditionalOnClass(JpaEntityManager.class) public class HibernateJpaAutoConfiguration { }八、条件测试SpringBootTest ConditionalOnProperty(name test.enabled, havingValue true) class ConditionalTest { Test void testConditionalBean() { // 测试条件Bean是否存在 } }总结条件装配是Spring Boot智能自动配置的基础通过合理使用条件注解可以构建灵活、可扩展的自动配置机制。自定义条件注解可以满足特殊场景的需求但应保持简洁和可维护性。