博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何使用Proxy模式及Java内建的动态代理机制
阅读量:6118 次
发布时间:2019-06-21

本文共 4265 字,大约阅读时间需要 14 分钟。

1.Proxy
模式
代理模式支持将某些操作从实际的对象中分离出来,通过它的代理类提供处理。这样便于修改和管理这些特定的操作。
下面示例一个代理模式的实现。
<<interface>>Subject.java
package
 com.zj.proxy;
 
public
 
interface
 Subject {
    
void
 operation1();
   
    
void
 operation2(String arg);
}
现实类RealSubject.java
package
 com.zj.proxy;
 
public
 
class
 RealSubject 
implements
 Subject {
 
    
public
 
void
 operation1() {
       System.
out
.println(
"Realer do operation1"
);
    }
 
    
public
 
void
 operation2(String arg) {
       System.
out
.println(
"Realer do operation2 with "
 + arg);
    }
}
代理类ProxySubject.java
package
 com.zj.proxy;
 
public
 
class
 ProxySubject 
implements
 Subject {
    
private
 Subject 
proxied
;
// 
被代理对象
 
    
public
 ProxySubject(Subject proxied) {
       
this
.
proxied
 = proxied;
    }
 
    
public
 
void
 operation1() {
       System.
out
.println(
"Proxyer do operation1"
);
       
proxied
.operation1();
    }
 
    
public
 
void
 operation2(String arg) {
       System.
out
.println(
"Proxyer do operation2 with "
 + arg);
       
proxied
.operation2(arg);
    }
}
测试类
SimpleProxyDemo.java
package
 com.zj.proxy.client;
 
import
 com.zj.proxy.Subject;
import
 com.zj.proxy.RealSubject;
import
 com.zj.proxy.ProxySubject;
 
public
 
class
 SimpleProxyDemo {
    
public
 
static
 
void
 consumer(
Subject
 subject) {
       subject.operation1();
       subject.operation2(
"ZJ"
);
    }
 
    
public
 
static
 
void
 main(String[] args) {
       RealSubject real = 
new
 RealSubject();
       System.
out
.println(
"===Without Proxy==="
);
       consumer(real);
       System.
out
.println(
"===Use Proxy==="
);
       consumer(
new
 ProxySubject(real));
    }
}
结果:
===Without Proxy===
Realer do operation1
Realer do operation2 with ZJ
===Use Proxy===
Proxyer do operation1
Realer do operation1
Proxyer do operation2 with ZJ
Realer do operation2 with ZJ
2.
使用
Java
的动态代理机制
设计一个类用于实现 InvocationHandle
接口, InvocationHandler 
是代理实例的调用处理程序实现的接口。
每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的  invoke 
方法。
<<interface>>InvocationHandle.java
package
 java.lang.reflect;
 
public
 
interface
 InvocationHandler {
    
public
 Object invoke(Object proxy, Method method, Object[] args)
    
throws
 Throwable;
}
对应 invoke
参数:
[1]proxy - 
在其上调用方法的代理实例;
[2]method - 
对应于在代理实例上调用的接口方法的  Method 
实例;
[3]args - 
包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为  null
现在设计一个类实现该接口,并提供代理实例。
DynamicProxyHandler.java
package
 com.zj.proxy.dynamic;
 
import
 java.lang.reflect.InvocationHandler;
import
 java.lang.reflect.Method;
 
public
 
class
 DynamicProxyHandler 
implements
 InvocationHandler {
    
private
 Object 
proxied
;
 
    
public
 DynamicProxyHandler(Object proxied) {
       
this
.
proxied
 = proxied;
    }
 
    
public
 Object invoke(Object proxy, Method method, Object[] args)
           
throws
 Throwable {
       System.
out
.println(
"**** proxy: ****\n"
 + proxy.getClass()
              
"\nmethod: "
 + method + 
"\nargs: "
 + args);
       
if
 (args != 
null
)
           
for
 (Object arg : args)
              System.
out
.println(
"  "
 + arg);
       
return
 method.invoke(
proxied
, args);
    }
}
这里的
private
 Object 
proxied
;
即代理实例,也即上文代理模式中介绍的 RealSubject
对象。
invoke()
方法中,我们会打印它的所有参数,并调用当前代理的方法。
测试类
DynamicProxyDemo.java
package
 com.zj.proxy.client;
 
import
 java.lang.reflect.Proxy;
import
 com.zj.proxy.Subject;
import
 com.zj.proxy.RealSubject;
import
 com.zj.proxy.dynamic.DynamicProxyHandler;
 
public
 
class
 DynamicProxyDemo {
    
public
 
static
 
void
 consumer(Subject subject) {
       subject.operation1();
       subject.operation2(
"ZJ"
);
    }
   
    
public
 
static
 
void
 main(String[] args) {
        RealSubject real = 
new
 RealSubject();
       System.
out
.println(
"===Without Proxy==="
);
       consumer(real);
       System.
out
.println(
"===Use Proxy==="
);
       Subject proxy = (Subject) Proxy.newProxyInstance(Subject.
class
              .getClassLoader(), 
new
 Class[] { Subject.
class
 },
              
new
 DynamicProxyHandler(real));
       consumer(proxy);
    }
}
这里通过 Proxy
的静态方法
newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
生成代理类,并传递与其关联的调用处理程序
new
 DynamicProxyHandler(real)
对于 newProxyInstance()
的参数:
[1]loader - 
定义代理类的类加载器 
[2]interfaces - 
代理类要实现的接口列表 
[3]h - 
指派方法调用的调用处理程序 
测试结果:
===Without Proxy===
Realer do operation1
Realer do operation2 with ZJ
===Use Proxy===
**** proxy: ****
class $Proxy0
method: public abstract void com.zj.proxy.Subject.operation1()
args: null
Realer do operation1
**** proxy: ****
class $Proxy0
method: public abstract void com.zj.proxy.Subject.operation2(java.lang.String)
args: [Ljava.lang.Object;@de6f34
  ZJ
Realer do operation2 with ZJ
从结果可以发现,通过代理可以得到当前被调用的方法,及其参数。代理过程可以基于此进行逻辑处理,测试程序只是简单的打印这些相关信息。
本文转自zhangjunhd51CTO博客,原文链接:http://blog.51cto.com/zhangjunhd/69996,如需转载请自行联系原作者
你可能感兴趣的文章
rsync 服务器配置过程
查看>>
预处理、const与sizeof相关面试题
查看>>
爬虫豆瓣top250项目-开发文档
查看>>
Elasticsearch增删改查
查看>>
oracle归档日志增长过快处理方法
查看>>
有趣的数学书籍
查看>>
teamviewer 卸载干净
查看>>
多线程设计模式
查看>>
解读自定义UICollectionViewLayout--感动了我自己
查看>>
SqlServer作业指定目标服务器
查看>>
UnrealEngine4.5 BluePrint初始化中遇到编译警告的解决办法
查看>>
User implements HttpSessionBindingListener
查看>>
抽象工厂方法
查看>>
ubuntu apt-get 安装 lnmp
查看>>
焊盘 往同一个方向增加 固定的长度方法 总结
查看>>
eclipse的maven、Scala环境搭建
查看>>
架构师之路(一)- 什么是软件架构
查看>>
jquery的冒泡和默认行为
查看>>
USACO 土地购买
查看>>
【原创】远景能源面试--一面
查看>>