快捷搜索:  as  2018  FtCWSyGV  С˵  test  xxx  Ψһ  w3viyKQx

澳门新葡新京返水_龟发之家论坛



注: 本文只是道理性子, 并不实用, 读者可用成熟稳定的开源权限系统如SpringSecurity. 但可参考实现自己的一些小框架.

在上课的时刻, 一位同砚拿着一篇JavaEye的很长的CGLIB解说代码来问我这是怎么回事?我看澳门新葡新京返水了下, 感觉那样的例子其实太让人难以一会儿看懂了, 于是就自己重造了个轮子.

Spring 2.5最大年夜的亮点便是基于评释实现设置设置设备摆设摆设, 着实这个谈不上什么亮点, EJB3/JPA早就实现了, 而且在道理上也只是使用反射里面的method.getAnnotation(MyAnnotaion.class)即可.

第二个不停大年夜张旗宣传捧的便是AOP, 着实AOP便是个JDK接口措施拦截器/子类增强, 不过Spring加了个设置设置设备摆设摆设文件封装, 而且和它的一直气势派头同等, 都是集成第三方的框架, 这里基于类增强的是CGLIB.

CGLIB是什么呢?

cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runti澳门新葡新京返水me. See samples and API documentation to learn more about features.

This library is free software, freely reusable for personal or commercial purposes.

cglib是一个强大年夜的,高机能,高质量的Code天生类库。它可以在运行期扩展Java类与实现Java 接口. 而CGLIB本身又用了ASM框架, 来避免直接解析字节码.

OK, 废话少说, 我们来经由过程一个例子看看基于评释和AOP的权限系统(本代码只必要CGLIB及其依附类库ASM, 或者直接下载cglib-nodep-2.2.jar http://sourceforge.net/project/showfiles.php?group_id=56933&package_id=98218&release_id=601998).

先看营业层:

public class MyClass {

private String role;// 运行时角色

public String getRole() {

return role;

}

public void setRole(String role) {

this.role = role;

}

@Role(name="admin")

public String adminMethod(String name) {

System.out.println("MyClass.adminMethod()" + name);

return "adminMethod 结果";

}

@Role(name="guest")

public String guestMethod(String name) {

System.out.println("MyClass.guestMethod()" + name);

return "guestMethod 结果";

}

}

基础上便是通俗的措施加上了角色评释, 当然评释类也是我们自己写的:

import java.lang.annotation.*;

@Documented

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})//指定目标, 必须包孕措施

@Retention(RetentionPolicy.RUNTIME)//设置维持性

@Inherited

public @interface Role {

String name();

}

所有的Magic都在后台经由过程反射和CGLIB的措施拦截器来实现, 先经由过程JDK本身的反射来反省评释, 然后读取评释的值, 随落后行判断并抉择是否履行此措施, 假如中心加上Spring容器, 那便是实现了所谓的专门的权限节制Bean了. 代码:

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;

import net.sf.cglib.proxy.MethodProxy;

import net.sf.cglib.proxy.MethodInterceptor;

public class Main {

public static void main(String[] args) {

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(MyClass.class);

enhancer.setCallback( new MethodInterceptorImpl() );

MyClass my = (MyClass)enhancer.create();

my.setRole("admin");

System.out.println(my.adminMethod("名字"));// 这一行将会履行经由过程

System.out.println(my.guestMethod("名字"));// 这一行将会履行掉败

/* --> new 父类 --> obj -->

* MyClass_proxy

* MyClass obj = new MyClass();// 原先父类

* MethodInterceptor interceptor;

public String method(String name) {

Object value = interceptor.intercept(obj, ojb.getClass().getMethod("method"), new Object[] {name},

proxy);

if(value != null) {

return value;

}

return obj.method(name);

}

*/

}

private static class MethodInterceptorImpl implements MethodInterceptor {

// obj => 父类的实例, method是被调用的措施, args = {String name}, proxy 专门履行措施的对象类

public Object intercept(Object obj,

Method method,

Object[] args,

MethodProxy proxy) throws Throwable {

System.out.println("即将调用措施" + method);

// 反省是否有Role评释 @Role(name="角色名")

Role role = method.getAnnotation(Role.class);

if(role != null) {

// 有评释

System.out.println("发明措施上" +method.getName() + " 有一个评释 Role澳门新葡新京返水, 它的值是" + role.name());

// 把被调用工具类型还原

MyClass my = (MyClass)obj;

if(!role.name().equals(my.getRole())) {

System.err.println("对不起, 您的权限不够, 不能调用此措施!");

throw new Exception("对不起, 您的权限不够, 不能调用此措施!");

}

else {

// ojb ==> MyClass my

// Before

Object value = proxy.invokeSuper(obj, args);// 正在调用措施

// invoke 等价于 String return = obj.method(args);

System.out.println("已经调用了措施, 蓝本应该返回的值:" + value);

// After

return value;

}

} else {

System.out.println("发明措施" +method.getName() + " 没有角色限定");

Object value = proxy.invokeSuper(obj, args);

return value;

}

}

}

class A {

String a() {

return "";

}

}

class A_proxy extends A {

A a = new A();

String a() {

String oldValue = a.a();

return oldValue;

}

}

}

别的评释着实是支持数组要领的变量定义的, 那样的话就可以写成:

@Role(name = {"guest", "admin"})

代码末真个类A和A_proxy试图阐明代理这种模式的实现要领. OK, 运行代码, 应该可以获得我们期望的结果了. admin措施履行成功, 而另一个则掉败了.

运行输出:

即将调用措施public void MyClass.setRole(java.lang.String)

发明措施setRole 没有角色限定

即将调用措施public java.lang.String MyClass.adminMethod(java.lang.String)

发明措施上adminMethod 有一个评释 Role, 它的值是admin

即将调用措施public java.lang.String MyClass.getRole()

发明措施getRole 没有澳门新葡新京返水角色限定

MyClass.adminMethod()名字

已经调用了措施, 蓝本应该返回的值:adminMethod 结果

adminMethod 结果

即将调用措施public java.lang.String MyClass.guestMethod(java.lang.String)

发明措施上guestMethod 有一个评释 Role, 它的值是guest

即将调用措施public java.lang.String MyClass.getRole()

发明措施getRole 没有角色限定

对不起, 您的权限不够, 不能调用此措施!

Exception in thread "main" java.lang澳门新葡新京返水.Exception: 对不起, 您的权限不够, 不能调用此措施!

at Main$MethodInterceptorImpl.intercept(Main.java:60)

at MyClass$$EnhancerByCGLIB$$e6aea994.guestMethod()

at Main.main(Main.java:20)

小结: 基于类的权限系统可经由过程CGLIB/AOP实现; 基于URL的权限系统可经由过程过滤器实现. 着实, Servlet的Filter也是AOP的一种基于Web的实现.

后记: 近来网上有一种很普遍的论调, 昔时夜家说XX不好的时刻, 有人说XX不可, 有本事你也去跑啊, 去导啊, 不可你就闭嘴. 我想这是一种转移话题的谬论, 举个例子: 假如病人被庸医给看逝世了, 他的家人是不是还不能说这医生治的不好, 不应该穷究责任, 由于他们不会看病啊? 吃菜的不必要会做菜, 然则吃菜的有权利评价菜是否好吃, 以是真正应该闭嘴的是说这种话的人. 以是我们评论框架短长的时刻, 有人就说了: 你说XXX框架不好, 那你有本事也自己去做一个啊; 这是相称荒唐的跑题的论调.

您可能还会对下面的文章感兴趣: