什么是实现注释的有效用例?
在设计主要基于注释的配置系统时,我偶尔需要创建实现代码生成或编程配置注释的类.
替代方案涉及将注释中包含的数据镜像到DTO中,这似乎是一种开销.
这是一个例子:
public enum IDType {
LOCAL,
URI,
RESOURCE;
}
@Documented
@Target( { METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Id {
/**
* @return
*/
IDType value() default IDType.LOCAL;
}
Run Code Online (Sandbox Code Playgroud)
随着实施
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;
}
}
Run Code Online (Sandbox Code Playgroud)
我得到了编译器警告,但它似乎是许多用例的有效工具.
以上示例的警告是
注释类型Id不应用作IdImpl的超接口
编辑:
我刚从Guice找到这个例子:
bind(CreditCardProcessor.class)
.annotatedWith(Names.named("Checkout"))
.to(CheckoutCreditCardProcessor.class);
Run Code Online (Sandbox Code Playgroud)
有没有人知道为什么存在这种限制或者还有其他一些用例?
Arn*_*sch 21
我从来没有在实践中使用它,但你得到的是,你可以使用类来替换你的注释.
让我们创造一个人为的例子.假设我们有一个文档生成器.它@Docu从给定的类中读取注释并打印该description属性.像这样:
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 {
}
Run Code Online (Sandbox Code Playgroud)
打印:
This is a static class!
This is another static class!
Run Code Online (Sandbox Code Playgroud)
我们现在想要实现的是,一个类不仅可以静态注释,而且可以向文档中添加运行时信息.我们很乐意在@Docu大多数时候使用注释,但是在特殊情况下我们需要特殊的文档.我们可能想为某些方法添加性能文档.我们可以通过让类实现注释来实现.生成器首先检查注释,如果不存在,则检查类是否实现注释.如果是,则将该类添加到注释列表中.
像这样(生成器中只有两行代码):
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;
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
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.
Run Code Online (Sandbox Code Playgroud)
您不必更改代码生成器,因为您可以使用该类作为注释的替换.
其他示例可以是使用注释或XML作为配置的框架.您可能有一个处理注释的处理器.如果您使用XML作为配置,您可以生成实现注释的类的实例,并且您的处理器可以对它们进行操作而无需进行任何更改!(当然还有其他方法可以达到同样的效果,但这是一种方法)
| 归档时间: |
|
| 查看次数: |
13089 次 |
| 最近记录: |