自定义一个场景,玩电脑和睡觉,电脑只能是人玩,但是人,猫,狗都可以睡觉
这里将玩游戏和睡觉抽象出两个方法:
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");
}
}
测试结果: