美文网首页Java高级编程
反射与代理设计模式

反射与代理设计模式

作者: 江湖非良人 | 来源:发表于2019-08-02 23:56 被阅读3次

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

传统代理设计模式的弊端

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

public class JavaAPIDemo {
    public static void main(String[] args)throws Exception{
        IMessage message=new MessageProxy(new MessageReal());
        message.send();
    }
}
interface IMessage{//传统代理设计必须有接口
    void send();//业务方法
}
class MessageReal implements IMessage {
    @Override
    public void send() {
        System.out.println("【发送消息】www.baidu.com");
    }
}
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();
        }
    }
}
传统代理设计

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

  以上的代理设计模式为静态代理设计,这种静态代理涉及的特点在于:一个代理类只为一个接口服务,如果现在准备有3000个业务接口,则按照此种做法就意味着需要编写3000个代理类,并且这些代理类操作形式类似。
  所以现在需要解决的问题在于:如何可以让一个代理类满足于所有的业务接口操作要求。

动态代理设计模式

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

  • 不管是动态代理类还是静态代理类都一定要接收真实业务实现子类对象;
  • 由于动态代理类不再与某一个具体的接口进行捆绑,所以应该可以动态获取类的接口信息。
动态代理设计模式

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

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;
  - InvocationHandler h:代理处理的方法;
  - Class<?>[] interfaces:代理是围绕接口进行的,所以一定要获取真实主体类的接口信息;

代理方法

范例:实现动态代理机制

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 message=(IMessage)new MLDNProxy().bind(new MessageReal());
        message.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 proxy, Method method, Object[] args) throws Throwable {
        System.out.println("【执行方法】"+method);
        Object returnData=null;
        if(this.connect()){
            returnData =method.invoke(target, args);
            this.close();
        }
        return returnData;
    }
}
interface IMessage{//传统代理设计必须有接口
    void send();//业务方法
}
class MessageReal implements IMessage {
    @Override
    public void send() {
        System.out.println("【发送消息】www.baidu.com");
    }
}

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

CGLIB实现代理设计模式

  从Java的官方已经明确的要求如果想要实现代理设计模式,那么一定是基于接口的应用,所以在官方给出的Proxy类创建代理对象时,都需要传递该对象所有的接口信息:

Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this)

  但是这个时候有一部分开发者就认为不应该强迫性的基于接口实现代理设计,所以一部分开发者就开发出了一个CGLIB开发包,利用这个开发包就可以实现基于类的代理设计模式。
1、CGLIB是一个第三方的程序包,将cglib-3.2.6.jar导入项目中;
2、编写程序类,该类不实现任何接口。

class Message  {
    public void send() {
        System.out.println("【发送消息】www.baidu.com");
    }
}

3、利用CGLIB编写代理类,但是这个代理类于需要做一个明确,此时相当于使用了类的形式实现了代理设计的处理,所以该代理设计需要通过CGLIB来生成代理对象,定义一个代理类:

class MLDNProxy implements MethodInterceptor{//方法拦截器配置
    private Object target;
    public MLDNProxy(Object target){
        this.target = target;//保存真实主体对象
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result = null;
        if(connect()){
            result= method.invoke(target, objects);
            this.close();
        }
        return result;
    }
    public boolean connect(){
        System.out.println("【消息代理】进行消息发送通道的连接。");
        return true;
    }
    public void close(){
        System.out.println("【消息代理】关闭消息通道。");
    }
}

4、此时如果想创建代理类对象,则就必须进行一系列的CGLIB处理。

public class JavaAPIDemo {
    public static void main(String[] args)throws Exception{
        Message message = new Message();//真实主体对象
        Enhancer enhancer=new Enhancer();//负责代理操作的程序类
        enhancer.setSuperclass(message.getClass());//假定一个父类
        enhancer.setCallback(new MLDNProxy(message));//设置代理类
        Message proxy= (Message) enhancer.create();//创建代理对象
        proxy.send();
    }
}

在进行代理设计模式定义时除了使用可以接口以外,还可以不受接口限制而实现基于类的代理设计,但从正常的设计角度出发,强烈建议还是基于接口的设计会比较合理。

相关文章

  • 反射与代理设计模式

      代理设计模式是在程序开发中使用最多的设计模式,代理设计模式的核心是有真实业务实现类和代理业务实现类,并且代理类...

  • 代理模式

    结构型设计模式 代理模式 分类 静态代理:运行之前代理类的 class 编译文件已经存在 动态代理:通过反射动态...

  • spring CGLIB 和 JDK动态代理

    AOP 使用的设计模式就是代理模式,是对IOC设计的补充。为了扩展性,往往会加上反射,动态生成字节码,生成代理类。...

  • 掌握java动态代理及原理有多难?

    前言:使用的jdk是1.7,需要了解反射机制 泛型 字节码登概念! 一、代理模式 代理模式是常用的java设计模...

  • 动态代理原理及在 Android 中的应用

    一、动态代理简介 1、什么是动态代理? 通过反射机制动态生成代理者对象的一种设计模式。 2、如何区分静态代理和动态...

  • java动态代理

    很久没写java代码了,继上次写完反射后我么这次来学习一下动态代理。 熟悉设计模式的人对于代理模式可 能都不陌生。...

  • 设计模式(十)代理模式

    本期我们将继续讨论设计模式,介绍代理模式,代理模式与很多设计模式有相似的地方,但其目的却又不同。如果读者多其他设计...

  • Java代理模式之静态代理与动态代理

    代理模式代理模式是常用的Java设计模式,特征是代理类与被代理类具有相同的接口,代理类主要负责为被代理类预处理消息...

  • Spring基础

    spring简介 基础技术 java 反射 xml xml解析 代理 大量设计模式 关键在于在容器中获取对象,sp...

  • 10、结构型模式-代理设计模式

    1、加盟商来啦-你需要掌握的代理设计模式 简介:讲解代理设计模式,让代理帮你完成工作 代理设计模式(Proxy P...

网友评论

    本文标题:反射与代理设计模式

    本文链接:https://www.haomeiwen.com/subject/vqtrdctx.html