You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在原生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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 13:50:45