当前位置: 首页 > news >正文

枚举和注解结合使用威力更大

注解的写法和接口很类似,都采用了关键字interface,而且都不能有实现代码,常量定义默认都是pulbic static final类型的.

他们的主要不同点是:注解在interface前加上@字符,而且不能继承,不能实现,这经常会给我们的开发带来一些障碍.

分析一个ACL(Access Contorl List ,访问控制列表)设计案例..看看如何避免这些障碍.

ACL中有三个重要的元素:

1.资源,有哪些信息是要被控制起来的.

2.权限级别,不同的访问者在规划在不同的级别中.

3.控制器(也叫鉴权人),控制不同的级别访问不同的资源.

鉴权人是整个ACL的实际核心,我们从最主要的鉴权人开始,看代码:

复制代码
//鉴权者接口
interface Identifier {
    //无权访问时的礼貌语
    String REFUSE_WORD = "您无权访问";
    // 鉴权
    public boolean identify();
}
复制代码

 

这是一个鉴权人的接口,定义了一个常量和一个鉴权方法,接下来应该实现该鉴权方法,但问题是我们的权限级别和鉴权方法之间是紧耦合的,若分拆成两个类显得有点啰嗦,怎么办?我们可以直接定义一个枚举来实现.

复制代码
//常用鉴权者
enum CommonIdentifier implements Identifier {
    //权限级别
    Reader, Author, Admin;

    //实现鉴权
    public boolean identify() {
        return false;
    }
}
复制代码

 

 定义了一个通用鉴权者,使用的是枚举类型,并且实现了鉴权者接口,现在就剩下资源定义了,这很容易定义,资源就是我们写的类,方法等,之后再通过配置来决定哪些类,方法允许什么级别的访问,这里的问题是:怎么把资源和权限级别关联起来呢?

使用XML配置文件?是个方法,但是对于我们的示例程序来说显得太过繁重,使用注解会更简洁些.需要首先定义出权限级别的注解,代码如下:

复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Access {
    //确定什么级别可以访问
    CommonIdentifier level() default CommonIdentifier.Admin;
}
复制代码

 

 该注解是标注在类上面的,并且会保留到运行期,我们定义一个资源类,代码如下:

复制代码
//商业逻辑,默认访问权限是Admin
@Access(level = CommonIdentifier.Author)
class Foo {

}
复制代码

 

Foo类只能是作者级别的人的访问,场景定义完毕,看如何模拟ACL的实现...看代码:

复制代码
 1 import java.lang.annotation.ElementType;
 2 import java.lang.annotation.Retention;
 3 import java.lang.annotation.RetentionPolicy;
 4 import java.lang.annotation.Target;
 5 
 6 public class Client {
 7     public static void main(String[] args) {
 8         //初始化商业逻辑
 9         Foo b = new Foo();
10         //获取注解
11         Access access = b.getClass().getAnnotation(Access.class);
12         //没有Access注解或者鉴权失败
13         if (access == null || !access.level().identify()) {
14             //没有Access注解或者鉴权失败
15             System.out.println(access.level().REFUSE_WORD);
16         }
17 
18     }
19 
20 }
21 
22 //商业逻辑,默认访问权限是Admin
23 @Access(level = CommonIdentifier.Author)
24 class Foo {
25 
26 }
27 
28 //鉴权者接口
29 interface Identifier {
30     //无权访问时的礼貌语
31     String REFUSE_WORD = "您无权访问";
32     // 鉴权
33     public boolean identify();
34 }
35 
36 //常用鉴权者
37 enum CommonIdentifier implements Identifier {
38     //权限级别
39     Reader, Author, Admin;
40 
41     //实现鉴权
42     public boolean identify() {
43         return false;
44     }
45 }
46 
47 @Retention(RetentionPolicy.RUNTIME)
48 @Target(ElementType.TYPE)
49 @interface Access {
50     //确定什么级别可以访问
51     CommonIdentifier level() default CommonIdentifier.Admin;
52 }
复制代码

 

打印输出:

您无权访问

 

这段代码,简单,易读,而且是通过ClassLoader类来解释该注解的,那会使开发更加简洁,所有的开发人员只要增加注解即可以解决访问控制问题.

 

//======================================================================

复制代码
 1 import java.lang.annotation.ElementType;
 2 import java.lang.annotation.Retention;
 3 import java.lang.annotation.RetentionPolicy;
 4 import java.lang.annotation.Target;
 5 
 6 public class Client {
 7     public static void main(String[] args) {
 8         MyAnno an1 = Foo.class.getAnnotation(MyAnno.class);
 9         MyAnno an2 = Impl.class.getAnnotation(MyAnno.class);
10         System.out.println(an1);//@cn.summerchill.test.MyAnno(desc=@cn.summerchill.test.MyAnno2(a=a1a))
11         System.out.println(an2);//@cn.summerchill.test.MyAnno(desc=@cn.summerchill.test.MyAnno2(a=aa))
12         System.out.println(an1.hashCode());//391187329
13         System.out.println(an2.hashCode());//391149008
14         System.out.println(an1.equals(an2));//false
15         System.out.println(an1 == an2);//false
16     }
17 }
18 
19 
20 @MyAnno(desc =@MyAnno2(a="a1a"))
21 class Foo {
22     public void doSomething(){
23         
24     }
25 }
26 @MyAnno(desc =@MyAnno2(a="aa"))
27 class Impl  {
28     
29     public void doSomething() {
30     }
31 }
32 
33 
34 @Retention(RetentionPolicy.RUNTIME)
35 @Target(ElementType.TYPE)
36 @interface MyAnno {
37     MyAnno2 desc();
38 }
39 
40 @interface MyAnno2{
41     String a() default "";
42 }
复制代码

 


本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/5640900.html,如需转载请自行联系原作者

相关文章:

  • 七个人生工具:SWOT、PDCA、6W2H、SMART、WBS、时间管理、二八原则
  • 剑指offer(一) 二维数组的查找
  • [vijos1554bzoj1411]硬币游戏快速幂
  • iPhone X Web 设计
  • 使用isolation forest进行dns网络流量异常检测
  • nginx 开机自动启动
  • Python监控服务器利器--psutil
  • 主线程退出,子线程会退出么?
  • apue读书笔记之apue.h的设置
  • rpm 安装中的问题
  • 编程学习初体验(3. 语言的选择)
  • oracle12C—RMAN表级恢复
  • 黑客的思想
  • RPC协议
  • 命令行工具软件
  • [译]如何构建服务器端web组件,为何要构建?
  • 「译」Node.js Streams 基础
  • Android系统模拟器绘制实现概述
  • CentOS7 安装JDK
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • emacs初体验
  • IOS评论框不贴底(ios12新bug)
  • java多线程
  • Java面向对象及其三大特征
  • JS数组方法汇总
  • MySQL-事务管理(基础)
  • MySQL用户中的%到底包不包括localhost?
  • Python学习之路16-使用API
  • SQLServer之索引简介
  • Zsh 开发指南(第十四篇 文件读写)
  • 大快搜索数据爬虫技术实例安装教学篇
  • 给Prometheus造假数据的方法
  • 猴子数据域名防封接口降低小说被封的风险
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 扩展资源服务器解决oauth2 性能瓶颈
  • 正则表达式-基础知识Review
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #pragma once
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (ZT)一个美国文科博士的YardLife
  • (分享)自己整理的一些简单awk实用语句
  • (简单) HDU 2612 Find a way,BFS。
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (学习日记)2024.01.19
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转)shell调试方法
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • * CIL library *(* CIL module *) : error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodu
  • ****Linux下Mysql的安装和配置
  • .NET 4.0中的泛型协变和反变
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .net中调用windows performance记录性能信息
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示