在平时开发过程中,使用注解是一件很平常的事情,但是至今没有自己编写过注解,于是打算自己搞个注解看一下处理流程。
下面的几个注解已经很熟悉了,是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