系统梳理Java注解

 在平时开发过程中,使用注解是一件很平常的事情,但是至今没有自己编写过注解,于是打算自己搞个注解看一下处理流程。

         下面的几个注解已经很熟悉了,是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来获取到注解的信息。

SOURCE,//注解在编译的时候被抛弃
CLASS,//编译到class文件中,但是虚拟机运行时不保留
RUNTIME//在class文件以及运行时的虚拟机中都能找到,可能被反射使用

@Target用来声明注解可以被添加在哪些类型的元素上,如类型、方法和域等。元素的值是一个数组,数据来源于枚举类型中。

TYPE,类、接口、或者枚举声明中
FIELD,属性
METHOD,方法
PARAMETER,参数
CONSTRUCTOR,构造方法
LOCAL_VARIABLE,局部变量
ANNOTATION_TYPE,注解
PACKAGE 包

@Documented  可以在javadoc中看到

@Inherited 注解中的数据可以被子类继承

 

 

(一)编译时处理注解

在JDK 6中,通过JSR 269把自定义注解处理器这一功能进行了规范化,有了新的javax.annotation.processing这个新的API。
对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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值