定义
为其他对象提供一种代理以控制对这个对象的访问
作用
为真实类提供角色预处理消息、过滤消息、消息转发、时候消息处理;
比如 : 虚代理 , 远程代理 , 写时复制 , Cache代理 , 防火墙代理 , 同步代理 , 智能指引 ,保护代理 。
常用结构
- Subject :目标接口。
- RealSubject : 具体的目标对象
- Proxy : 代理对象
实现方式
java中代理分为 静态代理 和 动态代理 , 这里重点讲动态代理 。
java中的动态代理,通过java的反射机制 和动态生成class的技术实现。代码如下 :
//动态代理类
public class DynamicProxy implements InvocationHandler{
//主题的接口
private Subject subject = null;
//日志记录
private final static Logger logger = LoggerFactory.getLogger(DynamicProxy.class);
/*
*绑定具体目标和接口
*@param RealSubject 具体目标,即实现类
*@return Subject 目标接口
*/
public Subject getProxyInterface(RealSubject real){
//将具体目标绑定到接口上
this.subject = real ;
//将动态代理和具体目标绑定
Subject subjectProxy = (Subject) Proxy.newProxyInstance(
real.getClass().getClassLoader(),
real.getClass().getInterface(),
this
);
return subjectProxy;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
if(method.getName().equals(".."))
{
...//相关处理
subject.***
//动态调用目标的方法
return method.invoke(subject,args);
}else{
***//相关处理
}
return null;
}
}
客户端调用:
public class Client{
public static void main(String[] args){
RealSubject real = ***** //实例化
DynamicProxy proxy = new DynamicProxy();
//realSubject现在是动态代理类了
Subject realSubject = proxy.getProxyInterface(real);
realSubject.*** //调用相关方法
}
}
通过代理类 ,彻底将接口的变化隔离了出去,当接口Subject发生变化的时候,动态代理类不需要关心,避免了静态代理的缺陷,但是,java自带的动态代理还必须知道接口的存在,接口Subject必须存在,在实际项目中,应当避免这种约束,可以使用cglib的代码生成库。
//动态代理类
public class ProxyCglib implements MethodInterceptor{
//主题的接口
private Subject subject = null;
//日志记录
private final static Logger logger = LoggerFactory.getLogger(ProxyCglib.class);
/*
*绑定具体目标和接口
*@param RealSubject 具体目标,即实现类
*@return Subject 目标接口
*/
public Subject getProxyInstance(RealSubject real){
//将具体目标绑定到接口上
this.subject = real ;
//将动态代理和具体目标绑定
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.subject.getClass());
enhancer.setCallback(this);
return (RealSubject)enhancer.create();
}
public Object intercept(Object obj,Method method,Object[] args,MethodProxy proxy) throws Throwable{
if(method.getName().equals(".."))
{
...//相关处理
//动态调用目标的方法
return proxy.invokeSuper(obj,args);
//或者
proxy.invokeSuper(obj,args);
return ;
}else{
***//相关处理
}
return null;
}
}
客户端调用:
public class Client{
public static void main(String[] args){
RealSubject real = ***** //实例化
ProxyCglib proxy = new ProxyCglib();
//realSubject现在是动态代理类了
Subject realSubject = (realSubject)proxy.getInstance(real);
realSubject.*** //调用相关方法
}
}
通过cglib,就可以避免接口的一定存在的问题。
更对cglib的介绍
百度文库
博文stone2083
SourceForge下载