您的位置:首页 > 编程语言 > Java开发

通过JDK动态代理和自定义注解来控制方法级别的权限访问

2017-08-17 19:46 761 查看
  自定义一个场景,玩电脑和睡觉,电脑只能是人玩,但是人,猫,狗都可以睡觉

  

  这里将玩游戏和睡觉抽象出两个方法:

    1.playComputer

    2.sleep

  

  将人和动物抽象出来成一个类:

    1.Animal

  但是怎么通过动态代理加自定义注解去让playComputer只能让人调用,sleep方法人,猫,狗都可以调用呢?

  有个思路就是,在方法上面加注解,且注解的内容就是允许访问该方法的Animal的type,在调用这个playComputer或者sleep方法的时候进行拦截,并且取出被调用那个方法上面的注解值与调用对象Animal的type进行比对,如果包含就访问这个方法,如果不包含就不调用.

  注意:这里使用的是jdk的动态代理,所以需要将注解放到接口上面,如果放到目标类的方法上面会导致读取不到,如果使用cglib的动态代理,当然那就不需要接口了,直接将注解放到目标类方法上面也能读取到注解的内容.

  如下工程:



  首先自定义注解,并且在里面定义人,猫,狗的常量:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {
String[] values();
static String HUMAN = "HUMAN";
static String DOG = "DOG";
static String CAT = "CAT";
}


  将人,猫,狗抽象成Animal类:

public class Animal {
private String name;
private String type;

getter and setter...
public String toString()...


  接口类:

public interface Deal {

@Secure(values = {Secure.HUMAN})
public String playComputer(Animal a);

@Secure(values = {Secure.HUMAN, Secure.CAT, Secure.DOG})
public String sleep(Animal a);
}


  目标类:

public class DealImpl implements Deal {
public String playComputer(Animal a) {
String re = a + " playComputer, DealImpl方法";
System.out.println(re);
return re;
}

public String sleep(Animal a) {
String re = a + " sleep,  DealImpl方法";
System.out.println(re);
return re;
}
}


  关键的代理类,里面将被调用的方法上面的注解内容取出,和调用者的类型进行匹配:

public class ProxyDeal implements InvocationHandler {

private Object target;

public Object bind(Object target) {
this.target = target;
Object targetProxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
return targetProxy;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Animal animal = null;
Object result = null;
if (null != args && args.length != 0) {
animal = (Animal) args[0];
}
if (method.isAnnotationPresent(Secure.class)) {
Secure annotation = method.getAnnotation(Secure.class);
String[] values = annotation.values();
if (null != values && values.length != 0) {
for (String value : values) {
if (value.trim().equals(animal.getType().trim())) {
result = method.invoke(target, args);
return result;
}
}
System.out.println("禁止访问:" + animal);
return null;
}
annotation.values();
}
return result;
}
}


  测试主函数:

public class SecureMain {
public static void main(String[] args) {
Deal deal = new DealImpl();
ProxyDeal proxy = new ProxyDeal();
Deal dealProxy = (Deal) proxy.bind(deal);
Animal animal = new Animal("zhangsan", Secure.CAT);
String re1 = dealProxy.playComputer(animal);
String re2 = dealProxy.sleep(animal);
System.out.println(re1 + "   main");
System.out.println(re2 + "   main");
}
}


  测试结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐