java设计模式学习笔记4 代理模式-动态代理

来源:互联网 发布:淘宝 性冷淡风知乎 编辑:程序博客网 时间:2024/05/22 08:23

因为静态代理模式有一些缺点,所以有了动态代理。

java的动态代理类位于java.lang.reflect包下,一般涉及以下两个类:

1、Interface InvocationHandler: 该接口定义了唯一一个方法

Object 

 invoke(Object proxy,Method method,Object[] args) 

实际使用的时候,第一个参数obj一般是指代理类的实例 ,method指的是被代理的方法,就像在静态代理中得那个request方法。args指的是参数数组。

2、Proxy: 也就是动态代理类,作用类似于静态代理案例中得ProxySubject

里面最重要的方法是:

static Object 

 newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 

返回的是一个代理类的实例,返回后的代理代理类,可以当做被代理类使用,即可以使用被代理类在Subject接口中声明过的方法。

所谓动态代理,Dynamic Proxy是一种在运行的时候生成的class,生成他的时候必须提供一组interface给他,可以把返回的这个类当做这些接口中的任意接口的实例来使用(多肽)

而代理终归是代理,他不会代替你做实际的工作,所以生成他的时候必须提供一个handler,即InvocationHandler,由他来接管实际工作。

所以在使用动态代理的时候,必须实现InvocationHandler接口,而就不用实现抽象角色Subject接口了。

一、还是建一个抽象角色,可以用抽象类,也可以用接口,但是动态代理只能用接口。应为创建代理类的时候需要具体角色实现的接口数组Class<?>[] interfaces。

/** * Created by charleszhu on 14-2-15. * 抽象角色 */public interface Subject {    public void request();}

二、新建真实角色,实现抽象角色

/** * Created by charleszhu on 14-2-15. * 真实角色 */public class RealSubject implements Subject {    @Override    public void request() {        System.out.println("realSubject invoked!!");    }}

三、建一个动态代理类,需要实现invocationHandler接口
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/** * Created by charleszhu on 14-2-15. */public class DynamicProxy implements InvocationHandler{    private Object sub; //需要有真实对象的引用,为了匹配所有类型,定义为Object类型,使用时候,通过构造函数传递对应类型    public DynamicProxy(Object sub) {        this.sub = sub;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("before request");        Object obj = method.invoke(sub,args);// 调用的就是传递对象的对应方法即,sub对应的方法,是真正的方法调用语句        System.out.println("after request");        return obj;    }}


四、测试
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;/** * Created by charleszhu on 14-2-15. */public class Client {    public static void main(String[] args) {        RealSubject realSubject = new RealSubject();        InvocationHandler handler = new DynamicProxy(realSubject);//构造函数传递相应对象        Class<?> classType = handler.getClass();        // 生成相应代理,因为传递realSubject类实现了Subject接口,生成的是$Proxy0这个类的实例,实现了Subject接口,所以可以转换为Subject的实例        // 当中realSubject.getClass().getInterfaces()也可以写作 new Class[]{Subject.class}        Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(),realSubject.getClass().getInterfaces(),handler);        subject.request();// 执行到此处,流程就会跳转到DynamicProxy类的invoke方法里。传递方法名与方法参数(底层自动完成)        System.out.println(subject.getClass());    }}
输出结果是:
before request
realSubject invoked!!
after request
class com.sun.proxy.$Proxy0

可以看到,subject是动态生成的代理类

0 0