反射注解
注解
什么注解?
注解:annotation(标识,标签),从Java5开始支持注解
注解能干什么?
注解是贴在java程序元素上面
程序元素 : 类,方法,字段,方法参数,接口,构造函数,枚举
注解贴在程序上面有什么用?
在反射的时候,动态可以获取字节码,方法,字段等等程序元素,获取了这些程序元素,那么就能获取程序元素上贴的注解。这些注解会参与程序运行提供比较的相关信息和数据
枚举是一个特殊类
注解是一个特殊的接口,所有的注解都继承自java.lang.annotation这个接口。
注解运行的过程
完整的注解(从编写到最终运行)需要三方面的参与。
1.需要定义一个注解。
2.需要一个被贴的程序元素(类,方法,字段,构造器等)
3.第三方程序的支持,底层的反射(赋予我注解的特殊功能
JDK中内置的注解
1.@Override 限定覆写父类方法 2.@Deprecated 标记已过时的成员,被标记的方法不推荐使用.
问题1:有的注解可以贴在类上,方法上,字段上,有的却只能贴在类上 问题2:有的注解可以有一个或者多个参数,有的却不行。 |
JDK中的元注解
注解: 贴在程序元素上面的标签
元注解 : 注解的注解(贴在注解上面的注解)
元注解 主要用于限定当前的注解能够贴在哪儿?能够保留在哪个阶段(程序执行三个阶段
源代码阶段,字节码阶段,JVM中)
@Retention: 表示注解可以保存在哪一个时期.
保存的时期的值,封装在RetentionPolicy枚举类中
枚举常量摘要 |
|
注解保留到字节码阶段,运行时候失效了 |
|
RUNTIME (常用) |
注解保留到运行阶段,运行时候使用反射获取做相应的程序处理-一般开发者自定注解都保留运行阶段 |
注解在源代码阶段有效,编译字节码就失效了 |
@Target: 表示注解可以贴在哪些位置(类,方法上,构造器上等等).
位置的常量封装在ElementType枚举类中:
ElementType.ANNOTATION_TYPE只能修饰Annotation
ElementType.CONSTRUCTOR只能修饰构造方法
ElementType.FIELD只能修饰字段(属性),包括枚举常量
ElementType.LOCAL_VARIABLE只能修饰局部变量
ElementType.METHOD只能修饰方法
ElementType.PACKAGE只能修饰包(极少使用)
ElementType.PARAMETER只能修饰参数
ElementType.TYPE只能修饰类,接口,枚举
|
自定义注解
- 定义一个注解
语法 : 注解关键字 @Interface
- 被贴的程序元素
- 第三方程序参与赋予注解功能(反射程序)
package cn.sxt.zhuji; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Column 注解 主要是解决通用反射jdbc操作 表名和 pojo实体对象名不配的情况 * * 使用方法:在被贴的程序元素上面使用 @注解名称(属性名=自定义属性值) */ /** * 设置注解的元注解 * 1,Target * 注解可以贴在那些程序元素上面 * 2, Retention * 注解可以保留到那个阶段,一般自定义保留到RUNTIME运行时 * */ @Target({ElementType.FIELD}) //可贴在字段申明上(包括枚举常量) @Retention(RetentionPolicy.RUNTIME) public @interface Colum { /* * 定义注解的属性 * 语法 * 数据类型 属性名称(); * * 如果属性名称 是 value()而且在使用的时候只用value一个属性,使用时候可以省略 * * 如:springMVC中 * @RequestMapping(value="/index") * @RequestMapping("/index") */ String value(); //String table(); }
package cn.sxt.zhuji; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE})//可贴在类、接口(包括注释类型)或枚举声明 public @interface Table { String value(); }
package cn.sxt.pojo; import cn.sxt.zhuji.Colum; import cn.sxt.zhuji.Table; //如果注释属性名不是value就必须写属性名 如:@Table(value="t_user") @Table("t_user") public class User { @Colum("username") private String name; private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public User() { super(); } public User(String name, String password) { super(); this.name = name; this.password = password; } @Override public String toString() { return "ZhuJie [name=" + name + ", password=" + password + "]"; } }
package cn.sxt.test; import java.lang.reflect.Field; import cn.sxt.pojo.User; import cn.sxt.zhuji.Colum; import cn.sxt.zhuji.Table; public class test { public static void main(String[] args) { /* * 第三方程序参与:底层通过反射获取被贴的程序元素,并获取注解,得到注解的属性值,辅助程序开发 */ // 1.获取User java类的字节码实例 Class<?> clz = User.class; //2.判断字节码实例上是否有 @Table注解 boolean at = clz.isAnnotationPresent(Table.class); //3.获取对应的注解 if(at) { //getAnnotation()如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null Table table= clz.getAnnotation(Table.class); System.out.println(table); System.out.println(table.value()); } //获取所有字段 Field[] field = clz.getDeclaredFields(); for (Field field2 : field) { if(field2.isAnnotationPresent(Colum.class)) { Colum cloum=field2.getAnnotation(Colum.class); System.out.println(cloum.value()); } } } }