因为静态代理模式有一些缺点,所以有了动态代理。
java的动态代理类位于java.lang.reflect包下,一般涉及以下两个类:
1、Interface InvocationHandler: 该接口定义了唯一一个方法
2、Proxy: 也就是动态代理类,作用类似于静态代理案例中得ProxySubject
里面最重要的方法是:
static Object | newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) |
所谓动态代理,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是动态生成的代理类