带有数组元素的 Java 自定义注解

标签 java spring java-8

我有一个自定义注释如下。

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnApiVersionConditional.class)
public @interface ConditionalOnApiVersion {

    int[] value() default 5;

    String property();
}

OnApiVersion条件是,

public class OnApiVersionConditional implements Condition {

  @Override
    public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
        final MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(ConditionalOnApiVersion.class.getName());

       attributes.get("value");


        final String inputVersion = context.getEnvironment().getProperty("userInputVersion");


    }

在我的 Bean 注释中,

  @Bean
  @ConditionalOnApiVersion(value = {6, 7}, property = "userInputVersion")

也有单版本匹配的bean,比如

@Bean
@ConditionalOnApiVersion(value = 8, property = "userInputVersion")

我想将属性文件中的 userInput 版本验证为可用的 Beans 支持版本。不确定,如何获取值、迭代并与 userInoutVersion 进行比较。该值可以是 8 或 {6,7} 作为 int 数组。不确定,我如何迭代该值以检查是否有任何值与输入版本匹配。

最终列表 apiVersions = attributes.get("value").stream().collect(Collectors.toList());

问题:

如何迭代 attributes.get("value") 并与 userInputVersion 进行比较?

attributes.get("value") 返回对象列表。

我尝试了下面的代码,

final List<Object> apiVersions = attributes.get("value").stream().collect(Collectors.toList());

boolean result = apiVersions.stream().anyMatch(version -> (int)version == Integer.parseInt(userInputVersion));

但是在第 2 行 anyMatch 中出现以下错误,

java.lang.ClassCastException: [I cannot be cast to java.lang.Integer

谢谢

最佳答案

您已经定义了一个很好的自定义注释,它使用 Spring 的 @Conditional,如果数组 value 中存在名为“property”的属性,则此过程只会创建 beans。

注解定义这两个变量如下:

  1. :int[](一个或多个受支持的版本)
  2. property:String(要比较的属性的名称)

当您使用元数据检索这些值时,Spring 将它们作为对象返回。将这些对象转换为您定义的类型是关键步骤。不需要流,因为迭代 int[] 数组很简单。

我测试了各种形式的注释(value = 5、value = {6,7} 等)并发现以下代码运行良好(@Conditional beans 仅在版本正确时创建)。

public class OnApiVersionConditional implements Condition {

@Override
public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {

    final MultiValueMap<String, Object> attributes = metadata
            .getAllAnnotationAttributes(ConditionalOnApiVersion.class.getName());

    // 1.  Retrieve the property name from the annotation (i.e. userInputVersion)
    List<Object> propertyObject = attributes.get("property");
    // 2.  Cast it to a String
    String propertyName = (String)propertyObject.get(0);

    // 3.  Retrieve the value 
    List<Object> list = attributes.get("value");
    // 4.  Cast it to int[]
    int[] values = (int[])list.get(0);

    // 5.  Look up the actual version (based on the property name in the annotation)
    final String inputVersion = context.getEnvironment().getProperty(propertyName);
    // Assume it is an integer? 
    int version = Integer.valueOf(inputVersion).intValue();

    // 6.  Scan the supported version; look to match against actual version
    for (int i : values)
        if (i == version)
            return true;

    // The version is not supported
    return false;

}

}

可以通过验证属性和值来改进此方法;如果其中任何一个包含错误/空值等,则返回 false。

关于带有数组元素的 Java 自定义注解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48600354/

相关文章:

java - Eclipse + Java 8 + 动态网络模块

java - 了解 Stream API ForEach Task 中的主循环

java - Spring 4 - 服务器启动后的运行方法

java - 使用 Streams API 收集器平均 BigDecimals

java - 将 JSON 值插入字符串

Java SimpleDateFormat 不抛出 ParseException

java - WebSphere 7 - 过多的垃圾收集会导致内存不足吗?

java - 创建新类型日期时出错

json - Jackson 对象映射器未使用映射器的 setDateFormat 或 setSerializationInclusion

java - Spring - 我什么时候应该考虑在同一个 JVM 中加载另一个上下文?