自定义注解和反射注释

自定义 Annotation

定义新的 Annotation 类型使用 @interface 关键字
 
声明注解的属性
  
•注解属性的作用:原来写在配置文件中的信息,可以通过注解的属性进行描述。
•Annotation 的属性声明方式:String name()或String[] likes();
•属性默认值声明方式:String name() default “xxx”;
•特殊属性value:如果注解中有一个名称value的属性,那么使用注解时可以省略value=部分,如@MyAnnotation(“xxx")
•特殊属性value[];
•枚举值之间使用逗号分隔
  例如:@MyAnnotation(name="jack",age=30,likes={"唱歌","跳舞"})
注:
a)注解属性没有访问控制修饰符public等修饰
b)注解无方法
c)注解属性中得到顺序无关
d)设置了默认值就不会报错了,当然也可以根据需求覆写默认值
e)注解类型可以是8种基本数据类型和其数组
f)value属性是个特殊的属性,可以省略
g)一定程度上可以替代参数属性文件,xml等文件
 
提取 Annotation 信息
 JDK 5.0 java.lang.reflect包下新增了 AnnotationElement接口, 该接口代表程序中可以接受注释的程序元素
 当一个 Annotation 类型被定义为运行时 Annotation , 该注释才是运行时可见, class 文件被载入时保存在 class 文件中的 Annotation 才会被虚拟机读取
 程序可以调用 AnnotationElement对象的如下方法来访问 Annotation 信息
   
 1 public class Demo2 {
 2     @MyAnnotation(who="jack",age=30,gender="male")//1、自定义注解的格式
 3     public void jump(){
 4     }
 5     
 6     @YouAnnotation//2、自定义注解默认值
 7     public void sleep(){
 8     }
 9     
10     @TheyAnnotation(value={"电视","洗衣机"})//3、自定义注解属性为数组
11     public void buy(){
12         
13     }
14     
15     @TheyAnnotation({"电脑","游戏"})//4、自定义注解属性为value时,可以省略属性,只写值
16     public void play(){
17         
18     } 
19     
20     public static void main(String[] args) {
21         Demo2 demo = new Demo2();
22         demo.jump();
23     }
24 }

 1、自定义注解格式验证

1 //自定义注解
2 public @interface MyAnnotation {
3     //属性
4     String who();
5     int age();
6     String gender();
7 }
1 public @interface YouAnnotation {2、自定义注解-默认值
2     String who() default "marry";
3     int age() default 22;
4     String gender() default "female";
5 }

 3、自定义注解数组

1 public @interface TheyAnnotation {
2     String[] value(); 
3 }

反射注解

  通过反射,动态的获取方法上面的注解。

 1 import java.lang.reflect.Method;
 2 import java.sql.Connection;
 3 import java.sql.DriverManager;
 4 
 5 public class Demo3 {
 6     //该方法中需要取得@DbInfo中的属性值,即反射注解
 7     @DbInfo
 8     public static Connection getConnection() throws Exception{
 9         //取得该类的字节码
10         Class clazz = Demo3.class;
11         //取得该类中名为getConnection()的公共方法
12         //参数一:方法名
13         //参数二:方法参数类型对应的字节码对象,没有的话,即null
14         Method method = clazz.getMethod("getConnection",null);
15         //通过该方法,取得方法上定义的注解
16         DbInfo dbInfo = method.getAnnotation(DbInfo.class);
17         //分别取得数据库连接参数
18         String driver = dbInfo.driver(); //如果注解上面没有@Retention(RetentionPolicy.RUNTIME),会报空指针异常,由于泛型在运行时,会被擦除。
19         String url = dbInfo.url();
20         String username = dbInfo.usrename();
21         String password = dbInfo.password();
22         Class.forName(driver);
23         Connection conn = DriverManager.getConnection(url,username,password);
24         return conn;
25     }
26     public static void main(String[] args) throws Exception {
27         Connection conn = getConnection();
28         if(conn!=null){
29             System.out.println("取得连接");
30             conn.close();
31         }
32     }
33 }

 反射注解

 1 import static java.lang.annotation.ElementType.CONSTRUCTOR;
 2 import static java.lang.annotation.ElementType.FIELD;
 3 import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
 4 import static java.lang.annotation.ElementType.METHOD;
 5 import java.lang.annotation.Documented;
 6 import java.lang.annotation.Inherited;
 7 import java.lang.annotation.Retention;
 8 import java.lang.annotation.RetentionPolicy;
 9 import java.lang.annotation.Target;
10 
11 @Inherited//该注解可被子类继承使用
12 @Documented//可用于JavaDoc工具提取成文档
13 @Target({METHOD})//注释使用于那个位置
14 @Retention(RetentionPolicy.RUNTIME)//注释有效的时间
15 public @interface DbInfo {
16     String driver() default "com.mysql.jdbc.Driver";
17     String url() default "jdbc:mysql://localhost:3306/bbs";;
18     String usrename() default "root";
19     String password() default "root";
20 }

 自定义注解归纳:

 1  a)定义注解格式如下:
 2     //自定义注解
 3       public @interface MyAnnotation {
 4           //属性
 5           String who();
 6           int age();
 7           String gender();
 8           //无方法
 9           }
10   b)设置默认值
11       public @interface YouAnnotation {
12           String who() default "marry";
13           int age() default 22;
14           String gender() default "female";
15           } 
16   c)数值情况:
17       public @interface TheyAnnotation {
18           String[] value(); //value是个特殊的属性,可以省略value名字
19       } 
20   d)注解可以在一定程度上替代参数,属性文件,XML文件
21   e)注解的策略[@Retention]
22        1)RetentionPolicy.SOURCE:源码级别上可见,在字节码级别和运行时不可见,无法反射 
23        2)RetentionPolicy.CLASS:字节码级别上可见,在运行时不可见,无法反射(默认)     
24        3)RetentionPolicy.RUNTIME:运行时可见,可以法反射,即在SOURCE和CLASS级别上都有
25   f)注解的位置[@Target]
26   g)写入文档[@Documented]
27       在使用javadoc命令写入html文档时,该注解一同被写入
28   h)继承性[@Inherited]
29       继承该类的子类依然具体父类该注解的特性
30       注意:元注解可以修饰其它注解,元注解本身也可由其它元注解或本身修饰

 

JDK 的元 Annotation

元 Annotation指修饰Annotation的Annotation。JDK中定义了如下元Annotation:

  @Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留的域, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 通过这个变量指定域。

    RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解. 这是默认值,class文件级别上。

    •RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注释,运行时。

    •RetentionPolicy.SOURCE: 编译器直接丢弃这种策略的注释,源码级别上。

  @Target:指定注解用于修饰类的哪个成员. @Target 包含了一个名为 value,类型为ElementType(JDK6)的成员变量。用于指定该Annotation作用的范围,方法,属性,字段等。

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})

  @Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc工具提取成文档。

  @Inherited: 被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注解

Myeclipse中添加JavaDoc文档注释快捷键:Atl+Shift+J

练习:基于注解,写一个具有权限认证功能的方法,有权限的用户可以查询表,无权限的用户不可以查询表

 1 import java.lang.reflect.Method;
 2 
 3 public class Demo4 {
 4     public static void find(){
 5         System.out.println("正在查询中。。。");
 6     }
 7     @Role
 8     public static void execute(String username, String password) throws Exception{
 9         if(username==null && password==null){
10             throw new Exception("需要参数");
11         }
12         Class clazz = Demo4.class;
13         Method method = clazz.getMethod("execute",String.class,String.class);
14         Role role = method.getAnnotation(Role.class);
15         if(role.username().equals(username) && role.password().equals(password)){
16             find();
17         }else{
18             System.out.println("你无权限执行该方法");
19         }
20     }
21     public static void main(String[] args) throws Exception {
22         execute("jack","123456");
23     }
24 }

注解应用-权限管理

 1 import static java.lang.annotation.ElementType.METHOD;
 2 import java.lang.annotation.Retention;
 3 import java.lang.annotation.RetentionPolicy;
 4 import java.lang.annotation.Target;
 5 
 6 @Target({METHOD})
 7 @Retention(RetentionPolicy.RUNTIME)
 8 public @interface Role {
 9     String username() default "jack";
10     String password() default "123456";
11 }

 

posted @ 2013-04-30 13:22  hacket520  阅读(990)  评论(1编辑  收藏  举报