@Repeatable注解的作用

参考答案

1.   @Repeatable注解的作用

JDK8 中增加了@Repeatable注解,是为解决同一个注解不能重复在同一类、方法、属性上使用的问题。

2.   @Repeatable注解的使用场景

举一个比较贴近开发的例子,在spring、springboot引入资源文件,可以使用注解@PropertySource。

@PropertySource("classpath:sso.properties")
public class Application {
}

把PropertySource中的value设置成String[]数组,引入多个资源文件。

public @interface PropertySource {
      ...
      String[] value();
}
@PropertySource({"classpath:sso.properties","classpath:dubbo.properties","classpath:systemInfo.properties"})
public class Application {
}

只是spring引入配置文件没有问题,如果注解中2个值存在依赖关系就不行了。例如:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
//@Repeatable(Validates.class)
public @interface Validate {

    /**
     * 业务类型
     * @return
     */
    String bizCode();

    /**
     * 订单类型
     * @return
     */
    int orderType();

}

上面的@validate注解,bizcode和orderType是一对一的关系,我希望可以添加注解:

@Validate(bizCode = "fruit",orderType = 1)
@Validate(bizCode = "fruit",orderType = 2)
@Validate(bizCode = "vegetable",orderType = 2)
public class BizLogic2 {
}

在java8之前,这种方式不行,但可以新建注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface Validates {

    Validate[] value();

}

注意:这个聚合注解默认约束value,以便存储子注解。

对应代码修改:

@Validates(value = {
        @Validate(bizCode = "fruit",orderType = 1)
        @Validate(bizCode = "fruit",orderType = 2)
        @Validate(bizCode = "vegetable",orderType = 2)
})
public class BizLogic2 {
}

在java8推出@Repeatable之后,不改动@Validates的情况下,对@Validate进行修改,增加@Repeatable(Validates.class),就可以在类上使用多个@Validate注解了。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(Validates.class)
public @interface Validate {

    /**
     * 业务类型
     * @return
     */
    String bizCode();

    /**
     * 订单类型
     * @return
     */
    int orderType();

}

再来看下,@PropertySource 和 @PropertySources都是这样。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource 

/**
 * Container annotation that aggregates several {@link PropertySource} annotations.
 *
 * <p>Can be used natively, declaring several nested {@link PropertySource} annotations.
 * Can also be used in conjunction with Java 8's support for <em>repeatable annotations</em>,
 * where {@link PropertySource} can simply be declared several times on the same
 * {@linkplain ElementType#TYPE type}, implicitly generating this container annotation.
 *
 * @author Phillip Webb
 * @since 4.0
 * @see PropertySource
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PropertySources

上述注释中可见,spring的4.0支持Java8这个特性。

3.   @Repeatable注解的原理

@Repeatable的原理,是语法糖。

反编译下面代码:

/*@Validates(value = {*/
        @Validate(bizCode = "fruit",orderType = 1)
        @Validate(bizCode = "fruit",orderType = 2)
        @Validate(bizCode = "vegetable",orderType = 2)
/*})*/
public class BizLogic2 {
}

结果:

@Repeatable注解的作用

再反编译下面代码试试:

/*@Validates(value = {*/
        @Validate(bizCode = "fruit",orderType = 1)
       // @Validate(bizCode = "fruit",orderType = 2)
        //@Validate(bizCode = "vegetable",orderType = 2)
/*})*/
public class BizLogic2 {
}

结果:

@Repeatable注解的作用

问题出现了,我以为添加@Repeatable之后,@Validate都会生成被语法糖@Validates包裹。没想到它很智能,只有一个@Validate注解时不转换。

所以使用多个@Validate时,要提前留坑,需要兼容1个或多个的场景。

感兴趣的童鞋可以测试下~

以上,是Java面试题【@Repeatable注解的作用】的参考答案。

 

输出,是最好的学习方法。

欢迎在评论区留下你的问题、笔记或知识点补充~

—end—

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧