代理模式
- Proxy Pattern, 23个经典模式的一种,又称委托模式
- 为目标对象提供(包装)了一个代理,这个代理可以控制对目标对象的访问
- 外界不用直接访问目标对象,而是访问代理对象,由代理对象再调用目标对象
- 代理对象中可以添加监控和审查处理
静态代理
- 代理对象持有目标对象的句柄
- 所有调用目标对象的方法,都调用代理对象的方法
- 对每个方法,需要静态编码(理解简单,但代码繁琐)
首先,实现接口:
public interface SayHello {
void sayHello();
}
其次,实现被代理对象:
public class JackSayHello implements SayHello {
@Override
public void sayHello() {
System.out.println("hello jack");
}
}
最后,实现静态代理类:
public class JackSayHelloProxy implements SayHello {
private JackSayHello jackSayHello; // 保存被代理对象
/**
* 构造函数,入参为被代理对象
*
* @param jackSayHello 被代理对象
*/
JackSayHelloProxy(JackSayHello jackSayHello) {
this.jackSayHello = jackSayHello;
}
@Override
public void sayHello() {
System.out.println("before");
jackSayHello.sayHello();
System.out.println("after");
}
}
调用方式:
public class Main {
public static void main(String[] args) {
JackSayHello jackSayHello = new JackSayHello();
JackSayHelloProxy jackSayHelloProxy = new JackSayHelloProxy(jackSayHello);
jackSayHelloProxy.sayHello();
}
}
但是静态对象的缺点很明显,一次只能代理一个对象
动态代理
- 对目标对象的方法每次被调用,进行动态拦截
首先实现代理处理器,用于拦截代理对象的方法:
/**
* 代理处理器
*/
public class ProxyHandler implements InvocationHandler {
// 被代理的接口
private SayHello sayHello;
ProxyHandler(SayHello sayHello) {
this.sayHello = sayHello;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 可以通过识别 method.getName 对接口中不同函数进行区别处理
if ("sayHello".equals(method.getName())) {
System.out.println("before sayHello");
Object result = method.invoke(sayHello, args);
System.out.println("after sayHello");
return result;
}
return null;
}
}
然后实现被代理接口和被代理对象,被代理对象可以有多个:
public interface SayHello {
void sayHello();
}
public class JackSayHello implements SayHello {
@Override
public void sayHello() {
System.out.println("hello jack");
}
}
public class TomSayHello implements SayHello {
@Override
public void sayHello() {
System.out.println("hello tom");
}
}
调用方法:
public class Main {
public static void main(String[] args) {
// 代理Jack
// 1.创建被代理对象
SayHello realImpl = new JackSayHello();
// 2.创建代理处理器
ProxyHandler proxyHandler = new ProxyHandler(realImpl);
// 3.动态生成代理对象
SayHello proxyInstance = (SayHello) Proxy.newProxyInstance(realImpl.getClass().getClassLoader(), realImpl.getClass().getInterfaces(), proxyHandler);
// 4.客户端通过代理对象调用方法,将自动被代理处理器的invoke方法拦截
proxyInstance.sayHello();
// 代理Tom
realImpl = new TomSayHello();
proxyHandler = new ProxyHandler(realImpl);
proxyInstance = (SayHello) Proxy.newProxyInstance(realImpl.getClass().getClassLoader(), realImpl.getClass().getInterfaces(), proxyHandler);
proxyInstance.sayHello();
}
}
结果:
before sayHello
hello jack
after sayHello
before sayHello
hello tom
after sayHello