实现注解的用例 [英] Use cases for implementing annotations

查看:30
本文介绍了实现注解的用例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

实现注解的有效用例有哪些?

What are valid use cases for implementing annotations?

在主要设计基于注解的配置系统时,我偶尔需要创建实现代码生成或编程配置注解的类.

When designing primarily annotation based configuration systems I occasionally need to create classes which implement annotations for code generation or programmatic configuration.

另一种方法是将注释中包含的数据镜像到 DTO 中,这似乎是一种开销.

The alternative involves mirroring the data contained in annotations into DTOs, which seems like an overhead.

这是一个例子:

public enum IDType {
    LOCAL,
    URI,
    RESOURCE;
}

@Documented
@Target( { METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Id {
    /**
     * @return
     */
    IDType value() default IDType.LOCAL;
}

与实施

public class IdImpl implements Id{

    private final IDType idType;

    public IdImpl(IDType idType){
        this.idType = idType;
    }

    @Override
    public IDType value() {
        return idType;
    }

    @Override
    public Class<? extends Annotation> annotationType() {
        return Id.class;
    }

}

我收到了编译器警告,但它似乎是许多用例的有效工具.

I get compiler warnings for this, but it seems to be a valid tool for many use cases.

上面例子的警告是

注解类型Id不应该是用作 IdImpl 的超接口

The annotation type Id should not be used as a superinterface for IdImpl

我刚刚从 Guice 中找到了这个例子:

I just found this example from Guice :

bind(CreditCardProcessor.class)
    .annotatedWith(Names.named("Checkout"))
    .to(CheckoutCreditCardProcessor.class);

请参阅此来自 Names 的 Javadoc.

有人知道为什么存在此限制或有其他一些用例吗?

Has anyone some information why this restriction exists or has some other use cases in mind?

推荐答案

我从未在实践中使用过它,但您得到的是,您可以使用类来替代您的注释.

I've never used it in practice but what you get is, that you can use classes as replacement for your annotations.

让我们创建一个人工示例.假设我们有一个文档生成器.它从给定的类中读取 @Docu 注释并打印 description 属性.像这样:

Let's create an artificial example. Say we have an documentation generator. It reads a @Docu annotation from given classes and prints the description attribute. Like this:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;

public class DokuGenerator {

    public static void main(String[] args) throws Exception {
        new DokuGenerator(StaticClass.class, StaticClass2.class);
    }

    public DokuGenerator(Class<?>... classesToDokument) throws Exception {
        List<Docu> documentAnnotations = getDocumentAnnotations(classesToDokument);
        printDocumentation(documentAnnotations);
    }

    private List<Docu> getDocumentAnnotations(Class<?>... classesToDokument)
            throws Exception {
        List<Docu> result = new ArrayList<Docu>();
        for (Class<?> c : classesToDokument)
            if (c.isAnnotationPresent(Docu.class))
                result.add(c.getAnnotation(Docu.class));
        return result;
    }

    private void printDocumentation(List<Docu> toDocument) {
        for (Docu m : toDocument)
            System.out.println(m.description());
    }

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Docu {
    String description();
}

@Docu(description = "This is a static class!")
class StaticClass {
}

@Docu(description = "This is another static class!")
class StaticClass2 {
}

打印:

This is a static class!  
This is another static class!

我们现在想要完成的是,一个类不仅可以静态注解,还可以将运行时信息添加到文档中.我们很乐意在大多数情况下使用 @Docu 注释,但在某些特殊情况下我们需要特殊的文档.我们可能希望为某些方法添加性能文档.我们可以通过让一个类实现注释来做到这一点.生成器首先检查注解,如果不存在,则检查该类是否实现了注解.如果是,它会将类添加到注释列表中.

What we now want to accomplish is, that a class can not only be staticly annotated, but can add runtime information to the documentation. We are quite happy to use the @Docu annotation most of the time, but there are special cases we want special documenation. We might want to add performance documenation for some methodes. We can do this by letting a class implement the annotation. The generator checks first for the annotation and, if not present, it checks if the class implements the annotation. If it does, it adds the class to the list of annotations.

像这样(生成器中只有两行额外的代码):

Like this (only two additional lines of code in the generator):

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DokuGenerator {

    public static void main(String[] args) throws Exception {
        new DokuGenerator(StaticClass.class, StaticClass2.class,
                DynamicClass.class);
    }

    public DokuGenerator(Class<?>... classesToDokument) throws Exception {
        List<Docu> documentAnnotations = getDocumentAnnotations(classesToDokument);
        printDocumentation(documentAnnotations);
    }

    private List<Docu> getDocumentAnnotations(Class<?>... classesToDokument)
            throws Exception {
        List<Docu> result = new ArrayList<Docu>();
        for (Class<?> c : classesToDokument)
            if (c.isAnnotationPresent(Docu.class))
                result.add(c.getAnnotation(Docu.class));
            else if (Arrays.asList(c.getInterfaces()).contains(Docu.class))
                result.add((Docu) c.newInstance());
        return result;
    }

    private void printDocumentation(List<Docu> toDocument) {
        for (Docu m : toDocument)
            System.out.println(m.description());
    }

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Docu {
    String description();
}

@Docu(description = "This is a static class!")
class StaticClass {
}

@Docu(description = "This is another static class!")
class StaticClass2 {
}

class DynamicClass implements Docu {

    public DynamicClass() {
        try {
            Thread.sleep((long) (Math.random() * 100));
        } catch (InterruptedException e) {
            // ignore exception to make debugging a little harder
        }
    }

    @Override
    public String description() {
        long millis = System.currentTimeMillis();
        new DynamicClass();
        millis = System.currentTimeMillis() - millis;
        return "This is a dynamic class. I run on "
                + System.getProperty("os.name")
                + ". The construction of an instance of this class run for "
                + millis + " milliseconds.";
    }

    @Override
    public Class<? extends Annotation> annotationType() {
        return Docu.class;
    }

}

输出为:

This is a static class!  
This is another static class!  
This is a dynamic class. I run on Windows XP. The construction of an instance of this class run for 47 milliseconds.

您不必对代码生成器进行太多更改,因为您可以使用该类来替换注释.

You havn't to change the code generator that much because you can use the class as replacement of the annotation.

其他示例应该是使用注释或 XML 作为配置的框架.您可能有一个处理注释的处理器.如果您使用 XML 作为配置,您可以生成实现注释的类的实例,并且您的处理器无需任何更改即可处理它们!(当然还有其他方法可以达到同样的效果,但这是一种方法)

Other example whould be a framework that uses annotations or XML as configuration. You might have one processor that works on annotations. If you use XML as configuration you can generate instances of classes that implement the annotations and your processor works on them without a single change! (of course there are other ways to accomplish the same effect, but this is ONE way to do it)

这篇关于实现注解的用例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆