JAVA中@Repeatable注解

阅读更多

    @Repeatable注解以及其相关特性,是在JDK 8中提供的,简单而言,我们可以设计一种风格的annotation,可以被多次修饰在符合要求的@Target上,在此前一个类型的注释是不能重复修饰在相同地方。被重复修饰的注解,表示此Target同时具有注解的驱动能力,比如下文的@Scheduled,表示此任务方法分别在各自的时机执行。

 

    对于JAVA开发人员,我们常见的、已经基于@Repeatable的注解,比如:

    1、@ComponentScan --- Spring

    2、@Scheduled --- Spring

 

    以Spring @Scheduled为例,我们简述一下其使用场景:

 

    1、@Scheduled元注解

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {

    //cron表达式
    String value();
}

 

    元注解与普通注解没有太大区别,比如target、集成关系等。唯一需要注意的时,需要使用@Repeatable表示其可以被重复修饰目标上,其中还要指定其容器注解类类型---@Schedules。由此可见,元注解和容器注解,需要互相关联。

 

    2、@Schedules容器注解类

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Schedules {

    Scheduled[] value();
}

 

    1)容器注解类的@Target设计上需要考虑周全,它是否可以像元注解一样单独使用;以上述为例,表明@Schedules也可以被直接使用。

    2)容器类,应该像例子所示,其value方法(默认方法)需要返回其元注解的列表,否则这个容器类设计将不符合规范。

 

    3、解析注解,我们分别使用java反射和spring辅助类实现:

public class TaskRunner {

    @Scheduled("0 0/15 * * * ?")
    @Scheduled("0 0 12 * ?")
    public void task1() {}

    @Schedules({@Scheduled("0 0/15 * * * ?"),
            @Scheduled("0 0 12 * ?")})
    public void task2() {}


    public static void main(String[] args) throws Exception{
        javaStyle();
        System.out.println("-----------");
        springStyle();
    }


    private static void javaStyle() throws Exception{
        Method[] methods = TaskRunner.class.getMethods();
        for (Method method : methods) {
            Schedules schedules = method.getAnnotation(Schedules.class);
            if (schedules == null) {
                continue;
            }
            Scheduled[] values = schedules.value();
            if (values == null) {
                continue;
            }
            for (Scheduled scheduled : values) {
                System.out.println(scheduled.value());
            }
        }
    }

    private static void springStyle() throws Exception {
        Method[] methods = TaskRunner.class.getMethods();
        for (Method method : methods) {
            Set schedules = AnnotatedElementUtils.getMergedRepeatableAnnotations(
                    method, Scheduled.class, Schedules.class);
            if (schedules == null) {
                continue;
            }
            for (Scheduled scheduled : schedules) {
                System.out.println(scheduled.value());
            }
        }
    }
}

 

    根据规范,@Scheduled元注解,不能与@Schedules容器注解同时修饰在同一个Target,否则会编译错误。

 

你可能感兴趣的:(JAVA中@Repeatable注解)