这是我参与更文挑战的第2天,活动详情查看: 更文挑战
代理模式的使用
在委托类和客户之间添加一层代理类,通过代理类来代理委托类的实现。简单来说就是生产厂家和消费者之间的商家代理。消费者从商家代理那边买到产品,消费者不用关心生产厂家的情况,而商家代理从生产厂家获取产品,生产厂家不用关心产品的销售。代理类在其中的优点在于:
- 隐藏委托类的实现。
- 委托类和和客户之间实现解耦。在不修改委托类的情况下,通过代理类可以做一些额外的操作。
静态代理
静态代理的原理在于手动实现一个代理类,如下面的ProxyHttp
类,内部持有一个DelegateHttp
委托类,通过调用代理类的方法来间接实现委托类。
interface HttpService {
void http(String msg,int target);
}
/**
* 委托类 ,实现HttpService接口
*/
static class DelegateHttp implements HttpService{
@Override
public void http(String msg, int target) {
System.out.println("delegate msg="+msg+" target="+target);
}
}
/**
* 静态代理类
*/
private static class ProxyHttp {
private DelegateHttp delegateHttp;
public ProxyHttp(DelegateHttp o) {
this.delegateHttp = o;
}
public void http(String msg, int target) {
delegateHttp.http(msg, target);
}
}
复制代码
静态代理的缺点在于:代理类在编译期实现,如果存在多个委托类,或者需要对委托类做一些额外的操作,就需要修改或者增加代理类。如果说修改的地方过多,改动过大的话,有些得不偿失。
动态代理
动态代理在运行期通过反射生成对应的代理类。动态代理中使用到了InvocationHandler
接口,实现该接口和对应的invoke
方法来调用委托类的实现。
public static void main(String[] args) {
DelegateHttp delegateHttp = new DelegateHttp();
getProxy(delegateHttp).http("this is proxy", 10000);
}
/**
* 代理类
*/
private static HttpService getProxy(HttpService delegateHttp) {
HttpInvocationHandler invocationHandler = new HttpInvocationHandler(delegateHttp);
return (HttpService) Proxy.newProxyInstance(HttpService.class.getClassLoader(),
new Class[]{HttpService.class}, invocationHandler);
}
/**
* 中介类
*/
static class HttpInvocationHandler implements InvocationHandler {
private Object delegate;
public HttpInvocationHandler(Object delegate) {
this.delegate = delegate;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("dynamic proxy start------");
Object result = method.invoke(delegate, objects);
System.out.println("dynamic proxy end------");
return result;
}
}
复制代码
InvocationHandler
相当于中介类,代理类调用中介类,而中介类中持有委托类对象引用。当调用委托类的方法时,会执行到InvocationHandler
的invoke
方法,我们可以在invoke
方法中做一些额外的操作,比如添加日志等。
敲黑板
代理模式是对委托类的实现进行代理,达到实现的扩展和解耦。注意啊动态代理只针对接口,如果是普通的类的话,会报错的。最后千万不要理解为是对接口的实现啊,我以前一直是这样认为的。
最后
动态代理的原理在于动态的生成一个$Proxy0
代理类,该类继承自Proxy并实现需要代理的接口。加入下面这句代码,可以查看并生成对应的代理类:
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END