静态代理设计模式

静态代理设计模式

代理设计模式是在程序开发中使用最多的设计模式,代理设计模式的核心是有真实业务实现类和代理业务实现类,而且代理类要完成比真实业务更多的处理操做。java

传统代理设计模式的弊端

全部的代理设计模式若是按照设计要求来讲,必须是基于接口的设计,也就是说须要首先定义出核心接口的组成。
范例:模拟一个消息发送的代理操做结构(传统代理设计)设计模式

public class JavaAPIDemo {
    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("【发送消息】www.mldn.cn");
    }
}
class MessageProxy implements IMessage {   //代理类
    private IMessage message;  //代理对象,必定是业务接口实例
    public MessageProxy(IMessage message){
        this.message=message;
    }
    @Override
    public void send() {
        if(this.connect()){
            this.message.send();  //消息的发送处理
            this.close();
        }
    }
    public boolean connect(){
        System.out.println("【消息代理】进行消息发送通道的链接。");
        return true;
    }
    public void close(){
        System.out.println("【消息代理】关闭消息通道。");
    }
}

执行结果:
image.pngide

 

image.png
传统代理设计this

以上的操做代码是一个最为标准的代理设计,可是若是要进一步的去思考会发现客户端的接口与具体的子类产生了耦合问题,因此这样的操做若是从实际的开发来说,最好再引入工厂设计模式进行代理对象的获取。spa

以上的代理设计模式为静态代理设计,这种静态代理涉及的特色在于:一个代理类只为一个接口服务,若是如今准备有3000个业务接口,则按照此种作法就意味着须要编写3000个代理类,而且这些代理类操做形式相似。设计

因此如今须要解决的问题在于:如何可让一个代理类知足于全部的业务接口操做要求。代理

动态代理设计模式

经过静态代理设计模式的缺陷能够发现,最好的作法是为全部功能一致的业务操做接口提供有统一的代理处理操做,而这就能够经过动态代理机制来实现,可是在动态代理机制中须要考虑到以下几点问题:code

  • 无论是动态代理类仍是静态代理类都必定要接收真实业务实现子类对象;
  • 因为动态代理类再也不与某一个具体的接口进行捆绑,因此应该能够动态获取类的接口信息。

 

image.png
动态代理设计模式对象

在进行动态代理实现的操做中,首先须要关注的就是一个InvocationHandler接口,这个接口规定了代理方法的执行。blog

public 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)

  • ClassLoader loader:获取当前真实主体类的ClassLoader;
  • Class<?>[] interfaces:代理是围绕接口进行的,因此必定要获取真实主体类的接口信息;
  • InvocationHandler h:代理处理的方法;

 

image.png
代理方法

范例:实现动态代理机制

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JavaAPIDemo {
    public static void main(String[] args)throws Exception{
        IMessage msg=(IMessage)new MLDNProxy().bind(new MessageReal());
        msg.send();
    }
}
class MLDNProxy 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 pro, Method method, Object[] args) throws Throwable {
        System.out.println("*****【执行方法: 】"+method);
        Object returnData = null;
        if(this.connect()){
            returnData = method.invoke(this.target, args);
            this.close();
        }
        return returnData;
    }
}
interface IMessage{  //传统代理设计必须有接口
    void send();  //业务方法
}
class MessageReal implements IMessage {
    @Override
    public void send() {
        System.out.println("【发送消息】www.mldn.cn");
    }
}

执行结果:
image.png

若是认真观察系统中提供的Proxy.newProxyInstance()方法,会发现该方法会使用大量的底层机制来进行代理对象的动态建立,全部的代理类是符合全部相关功能需求的操做功能类,它再也不表明具体的接口,这样在处理时就必须依赖于类加载器与接口进行代理对象的伪造。

相关文章
相关标签/搜索