代理模式:给某个对象提供代理对象,由代理对象控制原来对象的引用。一般情况在客户端和原对象之间不好沟通的时候,有代理对象来介于二者之间,完成沟通工作;一旦一个对象被代理对象管理,代理对象就可能对原来对象执行方法前后进行拦截处理。
先来看下类图:
演示下静态代理 首先给出抽象主题
public interface Subject { public void method();
}
接着给出具体主题
public class RealSubject implements Subject{ @Override
public void method() {
System.out.println("我是真实主题");
}
}
最后代理出现:
public class ProxySubject implements Subject { private Subject subject; public ProxySubject() {
} @Override
public void method() { if(subject==null){
subject=new RealSubject();
}
preMethod();
subject.method();
postMethod();
} private void postMethod() {
System.out.println("代理人在执行前搞点事");
} private void preMethod() {
System.out.println("代理人在执行后搞点事");
}
}
使用客户端程序跑一次试试
public class Client { public static void main(String[] args) {
Subject subject=new ProxySubject();
subject.method();
}
}
以上属于静态代理,比较简单。与之对应的是动态代理,在运行时间内创建代理对象,JDK提供了 Proxy 和InvokationHandler 来处理 首先构造动态代理类
public class DynamicProxy implements InvocationHandler{ private Object proxied;
public DynamicProxy(Object proxied) { this.proxied=proxied;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object instance=method.invoke(proxied, args);
after(); return instance;
} public void before(){
System.out.println("第一步");
} public void after(){
System.out.println("第二步");
}
}
客户端调用如下
public class DynamicClient { public static void main(String[] args) {
Subject real = new RealSubject();
Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class},
new DynamicProxy(real));
proxySubject.method();
}
}
动态代理创建对象过程可分为以下四个步骤: 1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...); 2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类 Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...}); 3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型 Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class}); 4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入 Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler)); 为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。 生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))