1、代理模式
为其他对象提供一种代理,并以控制对这个对象的访问。对一个对象进行访问控制的一个原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。
2、代理模式的角色
抽象角色:声明真实对象和代理对象的共同接口
代理角色:代理角色内部包含有真实对象的引用,从而可以操作真实对象。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
3、动态代理
它是可以动态的创建代理并动态的处理对所代理方法的调用。是在运行生成的类,在生成时你必须提供一组Interface给它,然后该class就宣称它实现了这些interface。你可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
在使用动态代理类时,我们必须实现InvocationHandler接口。
4、代理的两个类
(1)java.lang.reflect.Proxy
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类
(2)InvocationHandler
是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
5、代码展示
//test类
public class Test {
public static void main(String[] args){
//通过Proxy.newProxyInstance构建代理对象
RealSubject realSub = new RealSubject();
InvocationHandler handler = new DynamicSubject(realSub);
Class<?> classType = handler.getClass();
Subject sub = (Subject) Proxy.newProxyInstance(classType.getClassLoader(), realSub.getClass().getInterfaces(), handler);
System.out.println(sub.getClass());
/*输出:class com.sun.proxy.$Proxy0 新建的代理对象,它实现指定的接口
*/
//通过调用代理对象的方法去调用真实角色的方法。
//调用真实角色RealSubject的Request()方法
sub.Request();
/* 输出:
Method:public abstract void com.reflect.Proxy.Subject.Request(), Args:null
test RealSubject
*/
}
}
//代理角色
//包含真实角色的引用,从而可以操作真实角色
public class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject(Object obj){
this.sub = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Method:"+ method + ", Args:" + args);
method.invoke(sub, args);//使用Method.invoke()方法将请求转发给被代理对象
return null;
}
}
//真实角色
//代理对象所代表的真实角色,最终为代理角色引用的对象
public class RealSubject implements Subject {
@Override
public void Request() {
System.out.println("test RealSubject");
}
}
//定义抽象角色
//声明真实角色和抽象角色的接口
public interface Subject {
public void Request();
}