zoukankan      html  css  js  c++  java
  • 自定义注解和反射注释

    自定义 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 }
  • 相关阅读:
    2015年新的征程,我的博客开通啦!
    基于USB3.0、DP1.2的网络隔离数据安全传输方案
    USB OTG to PC USB API简介
    SMA2SATA、PCIe2SATA转换模块(也有叫:Sata Test Fixtures)
    SATA接口硬盘加密器
    SVN二次开发——让SVN、TSVN(TortoiseSVN)支持windows的访问控制模型、NTFS ADS(可选数据流、NTFS的安全属性)
    About USB Data Link Cable API
    蓝牙4.0BLE抓包(三) – 扫描请求和扫描响应
    nRF51822外设应用[2]:GPIOTE的应用-按键检测
    蓝牙4.0BLE抓包(二) – 广播包解析
  • 原文地址:https://www.cnblogs.com/hacket/p/3051806.html
Copyright © 2011-2022 走看看