@Target(ElementType.ANNOTATION_TYPE)的工作原理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@Target(ElementType.ANNOTATION_TYPE)的工作原理相关的知识,希望对你有一定的参考价值。
Java注释用@Target
注释标记,以声明可以由该注释修饰的可能连接点。 TYPE
枚举的FIELD
,METHOD
,ElementType
等值清晰且易于理解。
Question
为什么要使用@Target(ANNOTATION_TYPE)
值?带注释的注释有哪些优点?他们的贡献是什么?给我一个关于它如何工作以及为什么要使用它的想法的解释。一些已经存在且众所周知的使用示例也很棒。
您可以使用带注释的注释来创建元注释,例如在Spring中考虑@Transactional
的这种用法:
/**
* Shortcut and more descriptive "alias" for {@code @Transactional(propagation = Propagation.MANDATORY)}.
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(propagation = Propagation.MANDATORY)
public @interface RequiresExistingTransaction {
}
当您启用Spring来处理@Transactional
注释时,它将查找带有@Transactional
或其任何元注释的类和方法(使用@Transactional
注释的注释)。
无论如何,这只是一个如何使用带注释的注释的具体示例。我想这主要是像Spring这样的框架,使用它们是有意义的。
由@Target(ElementType.ANNOTATION_TYPE)
注释的每个注释称为Meta-annotation
。这意味着,您可以定义自己的自定义注释,这些注释是许多注释的合并,组合成一个注释以创建composed annotations
。
来自android世界的一个很好的例子是StringDef
表示带注释的String元素表示逻辑类型,并且其值应该是显式命名的常量之一。
@Retention(SOURCE)
@Target({ANNOTATION_TYPE})
public @interface StringDef {
/** Defines the allowed constants for this element */
String[] value() default {};
}
//--
@Retention(SOURCE)
@StringDef({POWER_SERVICE, WINDOW_SERVICE, LAYOUT_INFLATER_SERVICE})
public @interface ServicesName {}
public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
//--
@StringDef({SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY})
@Retention(RetentionPolicy.SOURCE)
public @interface WeekDays {}
public static final String SUNDAY = "sunday";
public static final String MONDAY = "monday";
public static final String TUESDAY = "tuesday";
public static final String WEDNESDAY = "wednesday";
public static final String THURSDAY = "thursday";
public static final String FRIDAY = "friday";
public static final String SATURDAY = "saturday";
...
public abstract Object getSystemService(@ServicesName String serviceName);
public abstract Object getDayOfWeek(@WeekDays String weekDay);
代码检查员将以与@ServicesName
相同的方式处理@WeekDays
和@StringDef
。因此,我们可以根据需要创建尽可能多的名为StringDef
并覆盖常量集。 @Target(ElementType.ANNOTATION_TYPE)
它是一个允许扩展注释使用的工具。
例如,如果注释看起来像
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeAnnotation {
String description() default "This is example for class annotation";
}
编译器会在这种情况下抱怨
@SomeAnnotation
public class SomeClass {
@SomeAnnotation // here it's complaning
public void someMethod(){}
}
如果你改变了
@Target(ElementType.TYPE)
至
@Target({ElementType.METHOD, ElementType.TYPE})
它不会再抱怨了。
注释基本上是与您的代码一起的附加元数据(信息)。它可以放在旁边类型(类,接口),方法和参数中。
它在编译时和运行时通常很有用。许多流行的API(如Java EE 5 +,Spring,AspectJ)都利用注释来实现代码清晰度和一致性。
使用注释通常允许代码更易读,更容易理解。
我建议你read through the annotation chapter on Java tutorial
在过去,元数据通常作为xml文件提供,如果有人必须查找不同的xml配置文件,那么很难有人试图理解代码。 latest Java servlet API allows mapping of servlet simply by using annotation -- as opposed of web.xml mapping:
@WebServlet("/response")
public class ResponseServlet extends HttpServlet {
// servlet code here...
}
以上是关于@Target(ElementType.ANNOTATION_TYPE)的工作原理的主要内容,如果未能解决你的问题,请参考以下文章