代理模式之Java动态代理

1. Overview

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

代理模式之Java动态代理

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;     
}

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动态代理)