如何在原生Spring(非Spring Boot)中实现@DependsOnProperty注解
实现原生Spring下的@DependsOnProperty注解(无需Spring Boot依赖)
完全可以在原生Spring环境下实现类似Spring Boot @DependsOnProperty 的功能,无需引入任何Spring Boot依赖。核心思路是自定义注解+Spring扩展处理器来实现属性条件判断逻辑,下面是具体步骤:
1. 自定义@DependsOnProperty注解
先定义和Spring Boot版本功能一致的注解,包含属性名、匹配值、是否反转判断等核心参数:
import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DependsOnProperty { // 需要检查的属性名 String name(); // 属性需要匹配的值,默认空(仅检查属性是否存在) String havingValue() default ""; // 是否反转判断逻辑(属性不匹配时才注册Bean) boolean matchIfMissing() default false; }
2. 实现Bean条件注册处理器
通过实现Spring的BeanFactoryPostProcessor接口,在Bean定义加载阶段检查并处理自定义注解,根据属性配置决定是否保留对应的Bean定义:
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.core.env.Environment; import org.springframework.core.env.StandardEnvironment; import org.springframework.util.StringUtils; public class DependsOnPropertyProcessor implements BeanFactoryPostProcessor { private Environment environment; public DependsOnPropertyProcessor() { this.environment = new StandardEnvironment(); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { String[] beanNames = beanFactory.getBeanDefinitionNames(); for (String beanName : beanNames) { var beanDefinition = beanFactory.getBeanDefinition(beanName); String beanClassName = beanDefinition.getBeanClassName(); if (StringUtils.hasText(beanClassName)) { try { Class<?> beanClass = Class.forName(beanClassName); processAnnotation(beanClass, beanName, beanFactory); // 处理@Bean方法上的注解(如果是通过@Configuration注册的Bean) if (beanClass.isAnnotationPresent(org.springframework.context.annotation.Configuration.class)) { for (var method : beanClass.getDeclaredMethods()) { if (method.isAnnotationPresent(DependsOnProperty.class)) { processAnnotation(method.getAnnotation(DependsOnProperty.class), beanName, beanFactory); } } } } catch (ClassNotFoundException e) { // 忽略无法加载的类,不影响其他Bean处理 continue; } } } } private void processAnnotation(Class<?> beanClass, String beanName, ConfigurableListableBeanFactory beanFactory) { if (beanClass.isAnnotationPresent(DependsOnProperty.class)) { DependsOnProperty annotation = beanClass.getAnnotation(DependsOnProperty.class); processAnnotation(annotation, beanName, beanFactory); } } private void processAnnotation(DependsOnProperty annotation, String beanName, ConfigurableListableBeanFactory beanFactory) { String propertyName = annotation.name(); String expectedValue = annotation.havingValue(); boolean matchIfMissing = annotation.matchIfMissing(); boolean propertyExists = environment.containsProperty(propertyName); boolean isMatch = false; if (propertyExists) { String actualValue = environment.getProperty(propertyName); isMatch = StringUtils.hasText(expectedValue) ? expectedValue.equals(actualValue) : true; } else { isMatch = matchIfMissing; } // 如果不匹配,移除该Bean定义 if (!isMatch) { beanFactory.removeBeanDefinition(beanName); } } }
3. 注册处理器到Spring容器
在原生Spring的配置中注册这个处理器,确保Spring启动时能执行它:
- 若使用Java配置:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean public DependsOnPropertyProcessor dependsOnPropertyProcessor() { return new DependsOnPropertyProcessor(); } // 示例Bean:仅当app.feature.enabled=true时才注册 @DependsOnProperty(name = "app.feature.enabled", havingValue = "true") @Bean public FeatureService featureService() { return new FeatureService(); } }
- 若使用XML配置:
<bean class="com.yourpackage.DependsOnPropertyProcessor"/> <bean id="featureService" class="com.yourpackage.FeatureService"> <annotation>@com.yourpackage.DependsOnProperty(name = "app.feature.enabled", havingValue = "true")</annotation> </bean>
4. 使用与验证
- 当系统属性或配置文件中存在
app.feature.enabled=true时,featureService会被正常注册到容器; - 若属性不存在或值不为
true,该Bean会被自动忽略; - 若需要属性不存在时才注册Bean,可设置
matchIfMissing = true,例如:
@DependsOnProperty(name = "app.feature.disabled", matchIfMissing = true) @Bean public FallbackService fallbackService() { return new FallbackService(); }
内容的提问来源于stack exchange,提问作者Alaa jawhar
相关产品推荐
相关产品推荐

