自定義注解類編寫的一些規則:
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] ?view plaincopy
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 ?MyClassAnnotation?{??????String?uri();?? ????String?desc();?? }?? 構造方法注解定義:
?
[java] ?view plaincopy
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.CONSTRUCTOR)???public ?@interface ?MyConstructorAnnotation?{???? ????String?uri();?? ????String?desc();?? }?? 方法注解定義:
?
?
[java] ?view plaincopy
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.METHOD)??public ?@interface ?MyMethodAnnotation?{???? ????String?uri();?? ????String?desc();?? }?? 字段注解定義:
?
?
[java] ?view plaincopy
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.FIELD)???public ?@interface ?MyFieldAnnotation?{???? ????String?uri();?? ????String?desc();?? }?? 最后定義一個測試類
?
?
[java] ?view plaincopy
import ?java.lang.reflect.Constructor;??import ?java.lang.reflect.Field;??import ?java.lang.reflect.Method;???? @MyClassAnnotation (desc="The?class?name" ,?uri="com.annotation.MySample" )??public ?class ?MyTest?{???? ????@MyFieldAnnotation (desc="The?class?field" ,?uri="com.annotation.MySample#id" )?? ????private ?int ?id;?? ?????? ????@MyConstructorAnnotation (desc="The?class?constructor" ,?uri="com.annotation.MySample#MySample" )?? ????public ?MyTest(){}?? ?? ????public ?int ?getId()?{?? ????????return ?id;?? ????}?? ?? ????@MyMethodAnnotation (desc="The?class?method" ,?uri="com.annotation.MySample#setId" )?? ????public ?void ?setId(int ?id)?{?? ????????this .id?=?id;?? ????}?? ?????? ?????? ????public ?static ?void ?main(String[]?args)?throws ?Exception?{?? ?????????? ????????Class<MyTest>?clazz?=?MyTest.class ;?? ?????????? ?????????? ????????MyClassAnnotation?myClassAnnotation?=?clazz.getAnnotation(MyClassAnnotation.class );?? ?????????? ????????System.out.println(myClassAnnotation.desc()+"?" +myClassAnnotation.uri());?? ?????????? ?????????? ????????Constructor<MyTest>?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()?);?? ????}?? ?????? }?? 輸出:
?
The class name com.annotation.MySample The class constructor com.annotation.MySample#MySample The class method com.annotation.MySample#setId The class field com.annotation.MySample#id
?
好了,上面是基本學習,我們在實際的項目中用在什么地方呢?我想我們都做過關于細粒度權限攔截的問題,在Struts2中可以根據登錄用戶所具有的的權限進行任一一個action方法的攔截,可以定義一個自定義方法注解,例如
?
[java] ?view plaincopy
@Retention (RetentionPolicy.RUNTIME)??@Target (ElementType.METHOD)??public ?@interface ?Permission?{???? ?????? ????String?module();?? ?????? ????String?privilege();?? ?????? }?? 比如有一個部門action,Department.action,有一個方法public String departmentlistUI(){}
?
?
可以這樣定義方法
?
[java] ?view plaincopy
@Permission (module="department" ,privilege="view" )??????public ?String?departmentlistUI(){?? }?? 然后自定定義一個權限攔截器PrivilegeInterceptor.java并在struts.xml中注冊,
?
在實現interceptor接口后,實現方法public String intercept(ActionInvocation invocation) throws Exception {}
?
在這里調用任一個action方法都會經過該攔截方法,通過invocation可以獲取當前調用的action的名字,以及調用的action的哪個方法,
?
通過這段代碼可以獲取action名字和方法名
?
[java] ?view plaincopy
String??actionName=invocation.getProxy().getActionName();?? ????????String??methodName=invocation.getProxy().getMethod();?? ?????????? ????????System.out.println("攔截到:action的名字:" +actionName+"方法名:" +methodName);?? 然后通過反射技術,獲取該方法上的自定義權限注解,獲取當前登錄的用戶(從session中),遍歷當前用戶的所擁有的權限組,并且遍歷任一個權限組下的所有的權限,看是否包括該方法上注解所需的權限。這樣就可以完成細粒度的action方法權限攔截了。
?
?
這只是個大體的思路
下面看一下,攔截器的具體實現該功能的代碼
?
[java] ?view plaincopy
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 ;?? ????} ?
轉載于:https://www.cnblogs.com/chengJAVA/p/3649909.html
總結
以上是生活随笔 為你收集整理的java反射--注解的定义与运用以及权限拦截 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。