反射与代理设计模式
1、静态代理设计模式
代理设计模式是在程序开发之中使用最多的设计模式,代理设计模式的核心是有真实业务实现类与代理业务实现类,并且代理类要完成比真实业务更多的处理操作
传统代理设计模式的弊端
所有的代理设计模式如果按照设计要求来讲,必须是基于接口的设计,也就是说需要首先定义出核心接口的组成
public class JavaDemo {
public static void main(String[] args) throws Exception {
IMessage message = new MessageProxy(new MessageReal());
message.send();
}
}
interface IMessage{ //传统代理设计必须有接口
public void send();
}
class MessageReal implements IMessage {
@Override
public void send() {
System.out.println("发送消息!!!");
}
}
class MessageProxy implements IMessage{ //代理类
private IMessage message; //代理对象,一定是业务接口实例
public MessageProxy(IMessage message){
this.message = message;
}
public boolean connect () {
System.out.println("消息代理:进行消息通道的连接");
return true;
}
public void close (){
System.out.println("消息代理:关闭消息通道");
}
@Override
public void send() {
if (connect()){
message.send(); //消息的发送处理
close();
}
}
}
以上的操作代码是一个最为标准的代理设计,但是如果要进一步的去思考会发现客户端的接口与具体的子类产生耦合问题,所以这样的操作如果从实际的开发来讲最好再引入工厂设计模式进行代理对象的获取
以上的代理设计模式为静态代理设计,这种静态代理设计的特点在于::一个代理类只为一个接口服务,那么如果准备了大量的业务接口,那么就需要编写大量的代理类,并且这些代理类的操作形式基本一致
所以需要解决的问题在于:如何可以让一个代理类满足于所有的业务接口操作要求
2、动态代理设计模式
动态代理需要考虑以下问题:
- 不管是动态代理类还是静态代理类都一定要接收真实业务实现子类对象
- 由于动态代理类不再与某一个具体的接口进行捆绑,所有应该可以动态获取类的接口信息
在进行动态代理实现的操作之中,首先需要关注的就是一个InvocationHandler,这个接口规定了代理方法的执行
interface InvocationHandler{
/**
* 代理方法调用,代理主题类里面执行的方法最终都是此方法
* @param proxy 要代理的对象
* @param method 要执行的接口方法名称
* @param args 传递的参数
* @return 某一个方法的返回值
* @throws Throwable 方法调用时出现的错误继续向上抛出
*/
public Object invoke(Object proxy , Method method , Object[] args) throws Throwable;
}
在进行动态代理设计的时候对于动态对象的创建是由JVM底层完成的,此时主要依靠的是java.lang.reflect.Proxy程序类,这个类中提供有一个核心方法:
- 代理对象:public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
- ClassLoader loader:获取当前真实主体类的ClassLoader
- Class<?> [] interfaces:代理是围绕接口进行的,所以一定要获取真实主题类的接口信息
- InvocationHandler h:代理处理的方法
实现动态代理机制
public class JavaDemo {
public static void main(String[] args) throws Exception {
IMessage message = (IMessage) new MessageProxy().bind(new MessageReal());
message.send();
}
}
interface IMessage{ //传统代理设计必须有接口
public void send();
}
class MessageReal implements IMessage {
@Override
public void send() {
System.out.println("发送消息!!!");
}
}
class MessageProxy implements InvocationHandler { //代理类
private Object target; //保存真实业务
/**
* 进行真实业务对象与代理业务对象之间的绑定处理
* @param target 真实业务对象
* @return Proxy生成的代理业务对象
*/
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader() , target.getClass().getInterfaces() , this);
}
public boolean connect () {
System.out.println("消息代理:进行消息通道的连接");
return true;
}
public void close (){
System.out.println("消息代理:关闭消息通道");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行方法:" + method);
Object returnData = null;
if (connect()) {
returnData = method.invoke(target, args);
close();
}
return returnData;
}
}
如果认真观察系统中提供的Proxy.newProxyInstance()方法会发现该方法会使用大量的底层机制来进行代理对象的动态创建,所有的代理类是复合所有相关功能需求的操作功能类,它不再代表具体的接口,这样在处理的时候就必须依赖与类加载器与接口进行代理对象的伪造
下一篇:反射与Annotation