代理模式之Java动态代理

来源:java认证发布时间:2012-11-12 13:13:00java认证视频

    1. Overview
    Java在java.lang.reflect包下,定义了自己的代理。利用这个包下的类,我们可以在运行时动态地创建一个代理类,实现一个或多个接口。并将方法的调用转发到你所指定的类。因为实际代理是在运行时创建的,所以称为:动态代理。

    Proxy:完全由java产生的,而且实现了完整的subject接口。
    InvocationHandler:Proxy上的任何方法调用都会被传入此类,InvocationHandler控制对RealSubject的访问。
    因为Java已经帮助我们创建了Proxy类,我们需要有办法告诉Proxy类你要做什么,我们不能像以前一样把代码写入到Proxy类中,因为Proxy类不是我们实现的。那么我们应该放在哪里?放在InvocationHandler类中,InvocationHandler类是响应代理的任何调用。我们可以吧InvocationHandler想成是代理收到方法调用后,请求做实际工作的对象。
    2. java.lang.reflect.InvocationHandler
    被代理实例所实现的一个接口,内部只有一个invoke()方法,签名如下;
    Java代码
    public Object invoke(Object proxy, Method method, Object[] args)
    当代理的方法被调用的时候,代理就会把这个调用转发给InvocationHandler,也就会调用它的invoke()方法。
    3. java.lang.reflect.Proxy
    提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类,我们经常使用的静态方式是:
    Java代码
    newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
    4. 示例:
    情形:自己可以查看修改姓名性别,但是不能修改rate。他人可以查看姓名,性别以及修改rate,但是不能修改姓名性别。
    4.1 定义一个接口:
    Java代码
    public interface Person {
    String getName();
    String getGender();
    void setName(String name);
    void setGender(String gender);
    void setRate(int rate);
    int getRate();
    }
    4.2 定义实现Person接口类
    Java代码
    public class PersonImpl implements Person {
    String name;
    String gender;
    String interests;
    int rate;
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getGender() {
    return gender;
    }
    public void setGender(String gender) {
    this.gender = gender;
    }
    public String getInterests() {
    return interests;
    }
    public void setInterests(String interests) {
    this.interests = interests;
    }
    public int getRate() {
    return rate;
    }
    public void setRate(int rate) {
    this.rate = rate;
    }[nextpage]
    4.3 定义OwnerInvocationHandler类,表示如果为本人,则可以进行修改查看姓名性别。
    Java代码
    public class OwnerInvocationHandler implements InvocationHandler{
    private Person personBean;
    public OwnerInvocationHandler(Person personBean){
    this.personBean = personBean;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
    throws IllegalAccessException {
    try {
    if(method.getName().startsWith("get")){//如果方法名为get,就调用person类内的get相应方法
    return method.invoke(personBean, args);
    }else if(method.getName().equals("setRate")){ // 如果方法是setRate,则抛出异常
    throw new IllegalAccessException("access deny");
    }else if(method.getName().startsWith("set")){  //如果为set,就调用person类内的set相应方法
    return method.invoke(personBean, args);
    }else {
    System.out.println("non method invoke");
    }
    } catch (InvocationTargetException e) {
    e.printStackTrace();
    }
    return null;
    }
    }
    4.4 定义NonInvocationHandler类,表示如果不为本人,则可以进行查看姓名性别和修改rate。
    Java代码
    public class NonInvocationHandler implements InvocationHandler{
    //
    private Person person;
    public NonInvocationHandler(Person person){
    this.person = person;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
    if(method.getName().startsWith("setRate")){
    return method.invoke(person, args);
    }else if (method.getName().startsWith("get")){
    return method.invoke(person, args);
    } else {
    System.out.println("non method invoke");
    return null;
    }
    }
    }
    4.5 测试类MyDynamicProxy
    Java代码
    public class MyDynamicProxy {
    public Person getOwnerPersonBeanProxy(Person person){
    return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(),
    person.getClass().getInterfaces(), new OwnerInvocationHandler(person));
    }
    public Person getNonPersonBeanProxy(Person person){
    return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(),
    person.getClass().getInterfaces(), new NonInvocationHandler(person));
    }
    public static void main(String[] args) {
    MyDynamicProxy mdp = new MyDynamicProxy();
    mdp.test();
    }
    public void test(){
    //
    Person person = getPersonBeanFromDB1();
    Person personProxy = getOwnerPersonBeanProxy(person);
    System.out.println(personProxy.getName());
    try {
    personProxy.setRate(2);
    } catch (Exception e) {
    System.out.println("can not setRate");
    }
    //
    Person person1 = getPersonBeanFromDB1();
    Person personProxy2 = getNonPersonBeanProxy(person1);
    System.out.println(personProxy2.getName());
    personProxy2.setRate(2);
    System.out.println(personProxy2.getRate());
    }
    private Person getPersonBeanFromDB1(){
    Person pb = new PersonImpl();
    pb.setName("remy");
    pb.setGender("girl");
    pb.setRate(1);
    return pb;     }
    输出结果:
    Java代码
    remy     can not setRate     remy     2

    编辑特别推荐:

    Java读取文件内容再编辑

    JS获取单选与多选按纽的值

    每一种文件类型所对应的ContentType

视频学习

我考网版权与免责声明

① 凡本网注明稿件来源为"原创"的所有文字、图片和音视频稿件,版权均属本网所有。任何媒体、网站或个人转载、链接转贴或以其他方式复制发表时必须注明"稿件来源:我考网",违者本网将依法追究责任;

② 本网部分稿件来源于网络,任何单位或个人认为我考网发布的内容可能涉嫌侵犯其合法权益,应该及时向我考网书面反馈,并提供身份证明、权属证明及详细侵权情况证明,我考网在收到上述法律文件后,将会尽快移除被控侵权内容。

最近更新

社区交流

考试问答