[改善Java代码]枚举和注解结合使用威力更大
注解的写法和接口很类似,都采用了关键字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的实现...看代码:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; public class Client {
public static void main(String[] args) {
//初始化商业逻辑
Foo b = new Foo();
//获取注解
Access access = b.getClass().getAnnotation(Access.class);
//没有Access注解或者鉴权失败
if (access == null || !access.level().identify()) {
//没有Access注解或者鉴权失败
System.out.println(access.level().REFUSE_WORD);
} } } //商业逻辑,默认访问权限是Admin
@Access(level = CommonIdentifier.Author)
class Foo { } //鉴权者接口
interface Identifier {
//无权访问时的礼貌语
String REFUSE_WORD = "您无权访问";
// 鉴权
public boolean identify();
} //常用鉴权者
enum CommonIdentifier implements Identifier {
//权限级别
Reader, Author, Admin; //实现鉴权
public boolean identify() {
return false;
}
} @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Access {
//确定什么级别可以访问
CommonIdentifier level() default CommonIdentifier.Admin;
}
打印输出:
您无权访问
这段代码,简单,易读,而且是通过ClassLoader类来解释该注解的,那会使开发更加简洁,所有的开发人员只要增加注解即可以解决访问控制问题.
//======================================================================
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; public class Client {
public static void main(String[] args) {
MyAnno an1 = Foo.class.getAnnotation(MyAnno.class);
MyAnno an2 = Impl.class.getAnnotation(MyAnno.class);
System.out.println(an1);//@cn.summerchill.test.MyAnno(desc=@cn.summerchill.test.MyAnno2(a=a1a))
System.out.println(an2);//@cn.summerchill.test.MyAnno(desc=@cn.summerchill.test.MyAnno2(a=aa))
System.out.println(an1.hashCode());//
System.out.println(an2.hashCode());//
System.out.println(an1.equals(an2));//false
System.out.println(an1 == an2);//false
}
} @MyAnno(desc =@MyAnno2(a="a1a"))
class Foo {
public void doSomething(){ }
}
@MyAnno(desc =@MyAnno2(a="aa"))
class Impl { public void doSomething() {
}
} @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnno {
MyAnno2 desc();
} @interface MyAnno2{
String a() default "";
}
[改善Java代码]枚举和注解结合使用威力更大的更多相关文章
- [改善Java代码]枚举项的数量限制在64个以内
为了更好的使用枚举,Java提供了两个枚举集合:EnumSet和EnumMap,这两个集合的使用方法都比较简单,EnumSet表示其元素必须是某一枚举的枚举项,EnumMap表示Key值必须是某一枚举 ...
- [改善Java代码] 枚举项数量限定为64个以内
建议89:枚举项的数量限制在64个以内 为了更好的使用枚举,java 提供了两个枚举集合:EnumSet和EnumMap,这两个集合的使用都比较简单,EnumSet表示其元素必须是某一枚举的枚举项,E ...
- [改善Java代码]推荐使用枚举定义常量
枚举和注解都是在Java1.5中引入的,虽然他们是后起之秀,但是功能不容小觑,枚举改变了常量的声明方式,注解耦合了数据和代码. 建议83:推荐使用枚举定义常量 一.分析 常量的声明是每一个项目中不可或 ...
- Java复习——枚举与注解
枚举 枚举就是让某些变量的取值只能是若干固定值中的一个,否则编译器就会报错,枚举可以让编译器在编译阶段就控制程序的值,这一点是普通变量无法实现的.枚举是作为一种特殊的类存在的,使用的是enum关键字修 ...
- [改善Java代码]不使用stop方法停止线程
线程启动完毕后,在运行可能需要终止,Java提供的终止方法只有一个stop,但是不建议使用此方法,因为它有以下三个问题: (1)stop方法是过时的 从Java编码规则来说,已经过时的方式不建议采用. ...
- [改善Java代码]使用构造块精炼程序
建议36: 使用构造代码块精炼程序 什么叫代码块(Code Block)?用大括号把多行代码封装在一起,形成一个独立的数据体,实现特定算法的代码集合即为代码块,一般来说代码块是不能单独运行的,必须要有 ...
- [改善Java代码]易变业务使用脚本语言编写
建议16: 易变业务使用脚本语言编写 Java世界一直在遭受着异种语言的入侵,比如PHP.Ruby.Groovy.JavaScript等,这些“入侵者”都有一个共同特征:全是同一类语言—脚本语言,它们 ...
- [改善Java代码]用枚举实现工厂方法模式更简洁
工厂方法模式(Factory Method Patter)是"创建对象的接口",让子类决定实例化哪一个类,并使一个类的实例化延迟到其子类.工厂方法模式在我们的开发工作中,经常会用到 ...
- [改善Java代码]使用构造函数协助描述枚举项
一.分析 一般来说,我们经常使用的枚举项只有一个属性,即排序号,其默认值是从0.1.2... ....但是除了排序号外,枚举还有一个(或多个)属性:枚举描述,它的含义是通过枚举的构造函数,声明每个枚举 ...
随机推荐
- 第二百八十四天 how can I 坚持
又是一个周一.今天感觉过得好艰辛啊,幸好晚上程秀通过生日请客,吃了顿大餐,还拿回了一瓶酒.哈哈. 其他也没什么了.晚上玩的挺好.不过,回来,老是渴,一直想喝水,现在是又困,又累啊,睡觉了.
- 将“Cocos2dx-截屏并设置图片尺寸 ”中cocos2d-x代码转换为2.2的代码
Cocos2dx-截屏并设置图片尺寸: http://www.cocos2dev.com/?p=522 2.2 代码如下: void HelloWorld::screenShoot() { CCSiz ...
- ColorNote.疑难解答
首先感谢你对colornote的支持 在使用此应用的过程中,存在任何问题,请先在此页面查看是否有对应的解决方案[Ctrl + F 搜索] 如果问题无法解决,请在页面下方留言,或者邮件light.z@q ...
- HDU 1702 http://acm.hdu.edu.cn/showproblem.php?pid=1702
#include<stdio.h> #include<string.h> #include<queue> #include<stack> #define ...
- [iOS UI进阶 - 2.2] 彩票Demo v1.2 UICollectionView基本
A.需要掌握的 设计.实现设置界面 cell的封装 UICollectionView的使用 自定义UICollectionView 抽取控制器父类 "帮助"功能 code sour ...
- javascript 获取HTML DOM父、子、临近节点
在Web应用程序特别是Web2.0程序开发中,经常要获取页面中某个元素,然后更新该元素的样式.内容等.如何获取要更新的元素,是首先要解决的问题.令人欣慰的是,使用JavaScript获取节点的方法有很 ...
- uva10474 简单排序查找 一次AC
题目很简单,加上读题20分钟一次AC.还是用到了快排qsort. #include<iostream> #include<cstdlib> using namespace st ...
- cookie.js 加载顺序问题
今天遇到一个问题,在使用cookie.js时,只有在jquery.js文件后加载整体才有效 有效加载顺序 <head> <script type="text/javascr ...
- CSS构造超链接
超链接边框 派生超链接 属性选择器超链接 动态超链接 图像翻转超链接 CSS工具提示 1.给链接加上边框 A:link { Color: #f00; Text- ...
- C#自定义控件的开发:Pin和Connector
C#自定义控件的开发:Pin和Connector 2009-08-03 14:46 wonsoft hi.baidu 我要评论(0) 字号:T | T 本文介绍了如何使用智能设备扩展C#自定义控件. ...