在一个Spring-Boot项目中,我使用@ConditionalOnProperty来 Select 是否加载一些Bean.它看起来如下所示:

@ConditionalOnProperty(
    prefix = "myservice",
    name = "implversion",
    havingValue = "a"
)
@Service
public class MyServiceImplA implements MyService {
   // ...
}

这允许我使用特定的配置文件来 Select 应该加载哪个Bean,例如接口的不同实现,具体取决于值myservice.implversiona还是b或任何其他值.

我想用一个用户更友好的注释来达到同样的效果,比如:

@OnMyServiceVersion(value = "a")
@Service
public class MyServiceImplA implements MyService {
   // ...
}

怎么可能做到这一点呢?


我试着用@Conditional注释我的定制批注并实现Condition接口,但我不知道如何以这种方式判断属性.Spring-Boot OnPropertyCondition extends SpringBootCondition不是public,所以我不能从那里开始,而且不允许扩展注释,所以我有点卡住了.

我还try 了以下几种方法,但都没有成功:

// INVALID CODE, DO NOT USE
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@ConditionalOnProperty(
    prefix = "myservice",
    name = "implversion",
    havingValue = OnMyServiceVersion.value()
)
public @interface OnMyServiceVersion {
    String value();
}

推荐答案

您可以使用@ConditionalOnProperty@OnMyServiceVersion批注添加注释,并将批注的value作为havingValue属性@ConditionalOnProperty的别名:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(prefix = "myservice", name = "implversion")
public @interface OnMyServiceVersion {

    @AliasFor(annotation = ConditionalOnProperty.class, attribute = "havingValue")
    String value() default "";

}

以下是一个完整的示例,它实际展示了这一点:

package com.example.demo;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Service;

@SpringBootApplication
public class CustomPropertyConditionApplication {

    public static void main(String[] args) {
        SpringApplication.run(CustomPropertyConditionApplication.class, "--myservice.implversion=b");
    }
    
    @Service
    @OnMyServiceVersion("a")
    static class ServiceA {
        
        ServiceA() {
            System.out.println("Service A");
        }
        
    }
    
    @Service
    @OnMyServiceVersion("b")
    static class ServiceB {
        
        ServiceB() {
            System.out.println("Service B");
        }
        
    }
    
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @ConditionalOnProperty(prefix = "myservice", name = "implversion")
    static @interface OnMyServiceVersion {
        
        @AliasFor(annotation = ConditionalOnProperty.class, attribute = "havingValue")
        String value() default "";
        
    }

}

这将在运行时输出Service B.如果将Main方法中的参数更改为--myservice.implversion=a,它将输出Service A.如果删除该参数,它也不会输出.

Java相关问答推荐

Java JAR环境(JRE)是否支持模块?

CriteriaQuery with max

如何配置ActiveMQ Artemis以使用AMQP 1.0和其他协议与Java

错误:在Liferay7.4中找不到符号导入com.liferay.portal.kernel.uuid.PortalUUID;";

通过合并Akka Streams中的多个慢源保持订购

Mac上的全屏截图在使用JavaFX时不能正常工作吗?

我如何解释这个错误?必需类型:供应商R,提供:收集器对象,捕获?,java.util.List java.lang.Object>>

使用多个RemoteDatabase对象的一个线程

Domino Designer 14中的保存代理添加了重影库

Java17支持哪个MapR版本?

如何获得凌空cookies ,并设置它在下一个请求- android

插入中的JOOQ序列,设置为VS值

从12小时开始的日期模式

循环不起作用只有第一个元素重复

JavaFX复杂项目体系 struct

在Java Spring JPA中插入包含对其他实体的引用的列

如何制作回文程序?

如何通过gradle命令行从build.gradle获得Java targetCompatibility

为什么Java编译器为没有参数的方法(getter方法)创建桥接方法

将在 Docker 中运行的 Spring Boot 连接到在 Docker 中运行的 PostgreSQL,无需 compose 文件?