在平时开发过程中,使用注解是一件很平常的事情,但是至今没有自己编写过注解,于是打算自己搞个注解看一下处理流程。
下面的几个注解已经很熟悉了,是java内在的几个注解。
@Override注释能实现编译时检查,你可以为你的方法添加该注释,以声明该方法是用于覆盖父类中的方法。如果该方法不是覆盖父类的方法,将会在编译时报错。例如我们为某类重写toString()方法却写成了tostring(),并且我们为该方法添加了@Override注释;
@Deprecated的作用是对不应该在使用的方法添加注释,当编程人员使用这些方法时,将会在编译时显示提示信息,它与javadoc里的@deprecated标记有相同的功能,准确的说,它还不如javadoc @deprecated,因为它不支持参数,
@SuppressWarnings与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数值都是已经定义好了的,我们选择性的使用就好了。
看下面简单的一个注解
* (1)注解的定义类似接口,只不过在interface前面加一个@符号。
* (2)方法的名称就是参数的名称,返回值类型就是参数的类型。
* (3)可以通过default来声明参数的默认值。
* (4)通过@Retention和@Target这样的元注解,用来声明注解本身的行为。
*/
public @interface BixiaoAanTest {
String name() default "bixiao";
int age() default 10;
}
比较常见的几种元注解
@Retention用来声明注解的保留策略,有CLASS、RUNTIME和SOURCE这三种,分别表示注解保存在类文件、JVM运行时刻和源代码中。只有当声明为RUNTIME的时候,才能够在运行时刻通过反射API来获取到注解的信息。
CLASS,//编译到class文件中,但是虚拟机运行时不保留
RUNTIME//在class文件以及运行时的虚拟机中都能找到,可能被反射使用
@Target用来声明注解可以被添加在哪些类型的元素上,如类型、方法和域等。元素的值是一个数组,数据来源于枚举类型中。
FIELD,属性
METHOD,方法
PARAMETER,参数
CONSTRUCTOR,构造方法
LOCAL_VARIABLE,局部变量
ANNOTATION_TYPE,注解
PACKAGE 包
@Documented 可以在javadoc中看到
@Inherited 注解中的数据可以被子类继承
(一)编译时处理注解
对Mirror API也进行了更新,形成了新的javax.lang.model包。注解处理器的使用也进行了简化,不需要再单独运行apt这样的命令行工具,Java编译器本身就可以完成对注解的处理。对于同样的功能,如果用JSR 269的做法,只需要一个类就可以了。
@SupportedSourceVersion(SourceVersion.RELEASE_6) @SupportedAnnotationTypes("annotation.Assignment") public class AssignmentProcess extends AbstractProcessor { private TypeElement assignmentElement; public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); Elements elementUtils = processingEnv.getElementUtils(); assignmentElement = elementUtils.getTypeElement("annotation.Assignment"); } public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(assignmentElement); for (Element element : elements) { processAssignment(element); } } private void processAssignment(Element element) { List<? extends AnnotationMirror> annotations = element.getAnnotationMirrors(); for (AnnotationMirror mirror : annotations) { if (mirror.getAnnotationType().asElement().equals(assignmentElement)) { Map<? extends ExecutableElement, ? extends AnnotationValue> values = mirror.getElementValues(); String assignee = (String) getAnnotationValue(values, "assignee"); //获取注解的值 } } } }
(二)运行时处理注解(通过反射获取注解信息,然后进行处理,可以通过动态代理来简化)
如下面例子
public class TestDO { @CheckPersons public String name;//通过注解来看校验用户名称 public TestDO(String name) { this.name = name; } public void doPrint(){ System.out.println(name); } public void doPrintByAnno() throws Exception{ CheckPersons check = TestDO.class.getField("name").getAnnotation(CheckPersons.class); if(name.equals(check.name())){ System.out.println(name+" OK "); }else{ System.out.println(name+" false"); } } public static void main(String[] args) throws Exception{ TestDO d1 = new TestDO("bixiao"); TestDO d2 = new TestDO("bixiao1"); d1.doPrintByAnno(); d2.doPrintByAnno(); } }
参考:http://www.infoq.com/cn/articles/cf-java-annotation