java 注解annotation的使用以及反射如何获取注解
一、注解基本知识
1、元注解
元注解是指注解的注解。包括 @retention @target @document @inherited四种。
1. annotation型定义为@interface, 所有的annotation会自动继承java.lang.annotation这一接口,并且不能再去继承别的类或是接口.
2. 参数成员只能用public或默认(default)这两个访问权修饰
3. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和string、enum、class、annotations等数据类型,以及这一些类型的数组.
4. 要获取类方法和字段的注解信息,必须通过java的反射技术来获取 annotation对象,因为你除此之外没有别的获取注解对象的方法
5. 注解也可以没有定义成员, 不过这样注解就没啥用了
自定义注解类时, 可以指定目标 (类、方法、字段, 构造函数等) , 注解的生命周期(运行时,class文件或者源码中有效), 是否将注解包含在javadoc中及是否允许子类继承父类中的注解, 具体如下:
1. @target 表示该注解目标,可能的 elemenettype 参数包括:
elemenettype.constructor 构造器声明 elemenettype.field 域声明(包括 enum 实例) elemenettype.local_variable 局部变量声明 elemenettype.method 方法声明 elemenettype.package 包声明 elemenettype.parameter 参数声明 elemenettype.type 类,接口(包括注解类型)或enum声明
2. @retention 表示该注解的生命周期,可选的 retentionpolicy 参数包括
retentionpolicy.source 注解将被编译器丢弃 retentionpolicy.class 注解在class文件中可用,但会被vm丢弃 retentionpolicy.runtime vm将在运行期也保留注释,因此可以通过反射机制读取注解的信息
3. @documented 指示将此注解包含在 javadoc 中
4. @inherited 指示允许子类继承父类中的注解
二、在java中如何使用
2.1、定义注解
package com.test.annotation; import java.lang.annotation.elementtype; import java.lang.annotation.retention; import java.lang.annotation.retentionpolicy; import java.lang.annotation.target; public class myannotation { /** * 注解类 * @author t4980d * */ @retention(retentionpolicy.runtime) @target(elementtype.type) public @interface myclassannotation { string uri(); string desc(); } /** * 构造方法注解 * @author t4980d * */ @retention(retentionpolicy.runtime) @target(elementtype.constructor) public @interface myconstructorannotation { string uri(); string desc(); } /** * 我的方法注解 * @author owner * */ @retention(retentionpolicy.runtime) @target(elementtype.method) public @interface mymethodannotation { string uri(); string desc(); } /** * 字段注解定义 * @author owner * */ @retention(retentionpolicy.runtime) @target(elementtype.field) public @interface myfieldannotation { string uri(); string desc(); } /** * * 可以同时应用到类上和方法上 * @author t4980d * */ @target({elementtype.type, elementtype.method}) @retention(retentionpolicy.runtime) public @interface yts { // 定义枚举 public enum ytstype { util, entity, service, model } // 设置默认值 public ytstype classtype() default ytstype.util; // 数组 int[] arr() default {3, 7, 5}; string color() default "blue"; } }
2.2、基本测试注解
package com.test.annotation; import java.lang.reflect.constructor; import java.lang.reflect.field; import java.lang.reflect.method; import com.test.annotation.myannotation.myclassannotation; import com.test.annotation.myannotation.myconstructorannotation; import com.test.annotation.myannotation.myfieldannotation; import com.test.annotation.myannotation.mymethodannotation; import com.test.annotation.myannotation.yts; import com.test.annotation.myannotation.yts.ytstype; @myclassannotation(desc = "the class", uri = "com.test.annotation.test") @yts(classtype =ytstype.util) public class testannotation { @myfieldannotation(desc = "the class field", uri = "com.test.annotation.test#id") private string id; @myconstructorannotation(desc = "the class constructor", uri = "com.test.annotation.test#mysample") public testannotation() { } public string getid() { return id; } @mymethodannotation(desc = "the class method", uri = "com.test.annotation.test#setid") public void setid(string id) { system.out.println(" method info: "+id); this.id = id; } @mymethodannotation(desc = "the class method sayhello", uri = "com.test.annotation.test#sayhello") @yts public void sayhello(string name){ if(name == null || name.equals("")){ system.out.println("hello world!"); }else{ system.out.println(name + "\t:say hello world!"); } } public static void main(string[] args) throws exception { class<testannotation> clazz = testannotation.class; // 得到类注解 myclassannotation myclassannotation = clazz.getannotation(myclassannotation.class); system.out.println(myclassannotation.desc() + " "+ myclassannotation.uri()); // 得到构造方法注解 constructor<testannotation> cons = clazz.getconstructor(new class[]{}); myconstructorannotation myconstructorannotation = cons.getannotation(myconstructorannotation.class); system.out.println(myconstructorannotation.desc() + " "+ myconstructorannotation.uri()); // 获取方法注解 method method = clazz.getmethod("setid", new class[]{int.class}); mymethodannotation mymethodannotation = method.getannotation(mymethodannotation.class); system.out.println(mymethodannotation.desc() + " "+ mymethodannotation.uri()); // 获取字段注解 field field = clazz.getdeclaredfield("id"); myfieldannotation myfieldannotation = field.getannotation(myfieldannotation.class); system.out.println(myfieldannotation.desc() + " "+ myfieldannotation.uri()); } }
2.3、通过反射解析
package com.test.annotation; import java.lang.reflect.method; import java.util.arrays; import com.test.annotation.myannotation.myclassannotation; import com.test.annotation.myannotation.mymethodannotation; import com.test.annotation.myannotation.yts; import com.test.annotation.myannotation.yts.ytstype; public class parseannotation { /** * 解析方法注解 * @param <t> * @param clazz */ public static <t> void parsemethod(class<t> clazz) { try { t obj = clazz.newinstance(); for (method method : clazz.getdeclaredmethods()) { mymethodannotation methodannotation = method.getannotation(mymethodannotation.class); if (methodannotation!=null) { //通过反射调用带有此注解的方法 method.invoke(obj, methodannotation.uri()); } yts yts = (yts) method.getannotation(yts.class); if (yts != null) { if (ytstype.util.equals(yts.classtype())) { system.out.println("this is a util method"); } else { system.out.println("this is a other method"); } system.out.println(arrays.tostring(yts.arr())); //打印数组 system.out.println(yts.color()); //输出颜色 } system.out.println("\t\t-----------------------"); } } catch (exception e) { e.printstacktrace(); } } /** * 解析类注解 * @param <t> * @param clazz */ public static <t> void parsetype(class<t> clazz) { try { yts yts = (yts) clazz.getannotation(yts.class); if (yts != null) { if (ytstype.util.equals(yts.classtype())) { system.out.println("this is a util class"); } else { system.out.println("this is a other class"); } } myclassannotation classannotation = (myclassannotation) clazz.getannotation(myclassannotation.class); if (classannotation != null) { system.err.println(" class info: "+classannotation.uri()); } } catch (exception e) { e.printstacktrace(); } } public static void main(string[] args) { parsemethod(testannotation.class); parsetype(testannotation.class); } }
三、注解应用案例
3.1、关于细粒度权限拦截的问题,在struts2中可以根据登录用户所具有的的权限进行任一一个action方法的拦截,可以定义一个自定义方法注解,例如
@retention(retentionpolicy.runtime)//代表permission注解保留在的阶段 @target(elementtype.method)//标注在方法上面 public @interface permission { /** 模块 */ string module(); /** 权限值 */ string privilege(); }
3、2 比如有一个部门action,department.action,有一个方法public string departmentlistui(){}可以这样定义方法
@permission(module="department",privilege="view") public string departmentlistui(){ }
3.3、然后自定定义一个权限拦截器privilegeinterceptor.java并在struts.xml中注册,在实现interceptor接口后,实现方法public string intercept(actioninvocation invocation) throws exception {},在这里调用任一个action方法都会经过该拦截方法,通过invocation可以获取当前调用的action的名字,以及调用的action的哪个方法,通过这段代码可以获取action名字和方法名。
string actionname=invocation.getproxy().getactionname(); string methodname=invocation.getproxy().getmethod(); system.out.println("拦截到:action的名字:"+actionname+"方法名:"+methodname);
4、然后通过反射技术,获取该方法上的自定义权限注解,获取当前登录的用户(从session中),遍历当前用户的所拥有的权限组,并且遍历任一个权限组下的所有的权限,看是否包括该方法上注解所需的权限。这样就可以完成细粒度的action方法权限拦截了。
private boolean validate(actioninvocation invocation) throws securityexception, nosuchmethodexception { string methodname=invocation.getproxy().getmethod(); method currentmethod = invocation.getaction().getclass().getmethod(methodname); if(currentmethod != null && currentmethod.isannotationpresent(permission.class)){ //得到方法上的注解 permission permission = currentmethod.getannotation(permission.class); //该方法上的所需要的权限 systemprivilege methodprivilege = new systemprivilege(new systemprivilegepk(permission.module(), permission.privilege())); //得到当前登录的用户 employee e = (employee) actioncontext.getcontext().getsession().get("loginuser"); //遍历当前用户下的所有的权限组 for(privilegegroup group : e.getgroups()){ //如果该权限组下包含,要访问该方法所需要的权限,就放行 if(group.getprivileges().contains(methodprivilege)){ return true; } } //说明遍历的该用户所有的权限组,没有发现该权限,说明没有该权限 return false; } //没有标注注解,表示谁都可以调用该方法 return true; }
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
上一篇: PHP解耦的三重境界(浅谈服务容器)
下一篇: Java AOP知识详细介绍