意义
将接口的调用统一到一个函数里处理,然后再去具体实例调用相应的方法,充当一个分发器的作用
user -> handler -> method
字典
动态:指的是在程序运行时才创建代理类
代理:与被代理类具有相同的属性,也就是被代理类有run方法,它也有run方法
保护代理:限制接口类的某些方法给特定的对象使用
Proxy类:Java反射包自带,其中newProxyInstance可以返回接口实现类的实例
组成
1.接口
Person类:其中有name与score相关的方法
自己本人可以修改名字但不能修改分数
别人可以修改分数不能修改名字
public interface PersonBean { String getName(); void setName(String name); int getScore(); void setScore(int score); }
2.实现接口的类
public class PersonBeanImpl implements PersonBean { private String name; private int score; public PersonBeanImpl (){ } public PersonBeanImpl (String name,int score){ this.name = name; this.score = score; } public String getName (){ return name; } public void setName (String name){ this.name = name; } public int getScore (){ return score; } public void setScore (int score){ this.score = score; } }
3.实现InvocationHandler的handler类
它的invoke方法利用反射,PersonBean的方法调用时会来调用invoke,因此可以在invoke方法体实现相应逻辑,
实例中就是限定某些方法允许调用,某些方法会抛出异常
3.1 自身handler:当创建这个handler实例时,就说明只能修改name不能修改score
public class OwnInvocationHandler implements InvocationHandler { // 需要代理的对象 private PersonBean personBean; OwnInvocationHandler (PersonBean personBean){ this.personBean = personBean; } // 代理设置规则 public Object invoke (Object proxy ,Method method, Object[] args) throws Throwable{ String methodName = method.getName(); // 自己不能设置自己的分数 if ("setScore".equals(methodName)) { throw new IllegalAccessException("自己不能给自己打分"); } else { return method.invoke(personBean, args); } } }
3.2 他人handler:当创建这个handler实例时,就说明只能修改score不能修改name
public class OtherInvocationHandler implements InvocationHandler { // 需要代理的对象 private PersonBean personBean; OtherInvocationHandler (PersonBean personBean){ this.personBean = personBean; } // 代理设置规则 public Object invoke (Object proxy ,Method method, Object[] args) throws Throwable{ String methodName = method.getName(); // 不能修改别人的名字 if ("setName".equals(methodName)) { throw new IllegalAccessException("不能修改别人的名字"); } else { return method.invoke(personBean, args); } } }
4.生产handler类的工厂
通过Proxy的newProxyInstance获取PersonBean对象
它的主要作用:将传入的personBean与指定的InvocationHandler绑定,当PersonBean调用方法时,会去InvocationHandler调用invoke方法
public class ProxyFactory { /** * 获得 个人 代理 * @param personBean * @return */ public PersonBean getOwnerProxy(PersonBean personBean) { return (PersonBean)Proxy.newProxyInstance(personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(), new OwnInvocationHandler(personBean)); } /** * 获得 其他人 代理 * @param personBean * @return */ public PersonBean getOtherProxy(PersonBean personBean) { return (PersonBean)Proxy.newProxyInstance(personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(), new OtherInvocationHandler(personBean)); } }
参考《Head First 设计模式》 -- P474