1、Annotation(注解)介绍
Annotation(注解)是JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。注解是以'@注解名'在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解、单值注解、完整注解三类。它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实现对这些元数据(用来描述数据的数据)的访问。另外,你可以在编译时选择代码里的注解是否只存在于源代码级,或者它也能在class文件中出现。
在javaEE经典的SSH框架中(Strtus,Spring,hibernate),都可以用过使用注解来减少配置,提高系统的灵活性,所以,学习注解,是很有必要的一件事。
2、Annotation学习
元注解
元注解也就是注解的注解,Java中提供了四种元注解,专门负责注解其他的注解,分别如下:
@Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。可选的RetentionPoicy参数包括:
RetentionPolicy.SOURCE: 停留在java源文件,编译器被丢掉
RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认)
RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解,因此可以通过反射机制读取注解的信息
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
ElementType.CONSTRUCTOR: 构造器声明
ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
ElementType.LOCAL_VARIABLE: 局部变量声明
ElementType.METHOD: 方法声明
ElementType.PACKAGE: 包声明
ElementType.PARAMETER: 参数声明
ElementType.TYPE: 类、接口(包括注解类型)或enum声明
@Documented将注解包含在JavaDoc中
@Inheried允许子类继承父类中的注解
3、自定义注解
下面写一个自定义的注解,不讨论他的实用性,只是学习注解的写法以及使用
一个枚举,为注解做数据准备:
package timeng.annotation;
/**
*
* 〈正则表达式规则枚举〉
* @author timeng
*/
public enum RegexRule {
/**
* email正則表達式規則
*/
EMAIL("^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"),
/**
* 數字正則表達式規則
*/
NUMBER("^[0-9]*$");
public String value;
RegexRule(String value) {
this.value = value;
}
}
定义注解格式:public @interface 注解名 {定义体}
注解参数的可支持数据类型:
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组
注解:
package timeng.annotation;
/**
*
* 〈正则表达式注解〉
* @author timeng
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface Regex {
/**
* 正则表达式
* @return
*/
RegexRule regexRule() default RegexRule.NUMBER;
}
注解解析类,非常关键
package timeng.annotationparse;
/**
*
* 〈注解解析通用類〉
*
* @author timeng
*/
public class AnnotationParseUtil {
public void parseMethod(Class clazz) throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException {
Object obj = clazz.getConstructor(new Class[] {}).newInstance(new Object[] {});
for (Method method : clazz.getDeclaredMethods()) {
DateFormat df = method.getAnnotation(DateFormat.class);
String name = "";
if (df != null) {
name = df.dateType().value;
method.invoke(obj, name);
}
}
}
/**
*
* 功能描述: <br>
* 〈调用指定类的指定方法,传参〉
*/
public void parseMethod(Object proxy, Method method, Object[] args) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException,
InstantiationException {
// Object obj = clazz.getConstructor(new Class[] {}).newInstance(new Object[] {});
Regex df = method.getAnnotation(Regex.class);
String name = "";
if (df != null) {
name = df.regexRule().value;
method.invoke(proxy, args[0], name);
}
}
}
使用注解的类
package timeng.test;
/**
*
* 〈用例〉
*
* @author timeng
*/
public class UseCase {
/*
* @DateFormat(dateType=DateType.DateOnly) public void formatDate(Date date,String type){ System.out.println(date);
* }
*/
@Regex(regexRule = RegexRule.EMAIL)
public void regexEmail(String unCheckedString, String regexRule) {
boolean rs = Pattern.compile(regexRule).matcher(unCheckedString).find();
// System.out.println(unCheckedString);
// System.out.println(regexRule);
System.out.println(rs);
}
}
测试类
package timeng.test;
/**
*
* 〈测试类〉
*
* @author timeng
*/
public class Test {
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException {
AnnotationParseUtil parse = new AnnotationParseUtil();
// parse.parseMethod(UseCase.class);
Object[] params = new Object[10];
params[0] = "123@qq.com";
UseCase useCase = new UseCase();
parse.parseMethod(useCase, UseCase.class.getDeclaredMethods()[0], params);
}
}
运行test类即可看到效果:Test类使用注解,来添加正则表达式的验证规则,本例验证了一个邮箱格式。