自定义注解和反射注释
自定义 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:
•RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解. 这是默认值,class文件级别上。
•RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注释,运行时。
@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 }