java注解与反射
一、Java中提供了四种元注解,专门负责注解其他的注解,分别如下
1、@Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。可选的RetentionPoicy参数包括:
RetentionPolicy.SOURCE: 停留在java源文件,编译器被丢掉
RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认)
RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解,因此可以通过反射机制读取注解的信息
2、@Target元注解,默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
ElementType.CONSTRUCTOR: 构造器声明
ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
ElementType.LOCAL_VARIABLE: 局部变量声明
ElementType.METHOD: 方法声明
ElementType.PACKAGE: 包声明
ElementType.PARAMETER: 参数声明
ElementType.TYPE: 类、接口(包括注解类型)或enum声明
3、@Documented将注解包含在JavaDoc中
4、@Inheried允许子类继承父类中的注解
二、注解的定义
1、注解定义的格式
public @interface FieldMeta {}
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { public String name() default "fieldName"; public String setFuncName() default "setField"; public String getFuncName() default "getField"; public boolean defaultDBValue() default false; }
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Column { public String name() default "fieldName"; public String setFuncName() default "setField"; public String getFuncName() default "getField"; public boolean defaultDBValue() default false; }
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitColor { /** * 颜色枚举 * @author peida * */ public enum Color{ BULE,RED,GREEN}; /** * 颜色属性 * @return */ Color fruitColor() default Color.GREEN; }
三,使用
public class Apple { @FruitName("Apple") private String appleName; @FruitColor(fruitColor=Color.RED) private String appleColor; }
4、反射 结合使用
定义了一个可以作用于类、接口、枚举上的注解MyType。
Documented
@Target({ ElementType.TYPE})
@Retention(RUNTIME)
public @interface MyType {
String value() default "";
String className() default "";
}
定义了一个可以作用于类的方法上的注解MyMethod。
@Documented
@Target({ ElementType.METHOD})
@Retention(RUNTIME)
public @interface MyMethod {
String value() default "";
String methodName() default "";
}
定义了一个可以作用于类内部变量的注解MyField。
@Documented
@Target({ ElementType.FIELD})
@Retention(RUNTIME)
public @interface MyField {
String value() default "";
String name() default "";
String type() default"String";
}
下面我们写个例子,定义一个类使用这些注解。
@MyType(value = "test", className = "TestClass")
public class TestClass {
@MyField(value = "testNum", name="num", type = "int")
private int num;
@MyField(value = "testName", name="name", type = "String")
private String name;
@MyMethod(value = "print ")
public String print(){
return "hello annotation";
}
}
下面我们写一个类来实现读取注解属性并打印出来。
public class PrintAnnotation {
private String allAnnotation = new String();
public String printAllAnnotation(){
Set<Class<?>> clazzes = new Reflections("com.monkey01").getTypesAnnotatedWith(MyType.class);
for (Class<?> clazz : clazzes) {
printMyType(clazz);
}
System.out.println(allAnnotation);
return allAnnotation;
}
private void printMyType(Class<?> clazz) {
MyType myType = clazz.getAnnotation(MyType.class);
allAnnotation = allAnnotation + clazz.getName() + ": " + myType.value() + "-" + myType.className() + "\n";
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
MyField myField = field.getAnnotation(MyField.class);
if(myField != null) {
allAnnotation = allAnnotation + myField.value() + "-" + myField.name() + "-" + myField.type() + "\n";
}
}
Method[] methods = clazz.getMethods();
for(Method method : methods){
MyMethod myMethod = method.getAnnotation(MyMethod.class);
if(myMethod != null) {
allAnnotation = allAnnotation + myMethod.methodName() + "-" + myMethod.value() + "\n";
}
}
}
}
从代码可以看到首先通过反射来获取com.monkey01包下的使用了MyType注解的类。
Set<Class<?>> clazzes = new Reflections("com.monkey01").getTypesAnnotatedWith(MyType.class);
public static void getField(){
try {
Class clazz= Class.forName("com.http.model.HttpRequest");
Field[] field=clazz.getDeclaredFields();
//System.out.println(field.length);
for(Field f:field){
boolean isExist=f.isAnnotationPresent(FieldMeta.class);
if(isExist){
FieldMeta tt=f.getAnnotation(FieldMeta.class);
System.out.println("--注解:"+tt.id()+" "+tt.name());
}
System.out.println(f.getName());
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//反射获取对象方法名称
public static void getMethod(){
try {
Class clazz = Class.forName("com.http.model.HttpRequest");
Method[] method=clazz.getDeclaredMethods();
System.out.println(method.length);
for(Method f:method){
System.out.println(f.getName()); //获取方法名
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}