静态代理设计模式 | 带你学《Java语言高级特性》之九十五

简介: 本节介绍了静态代理设计模式的弊端以及解决方案:实现动态代理机制。

上一篇:ClassLoader类加载器 | 带你学《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.png

image.png
传统代理设计

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

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

所以现在需要解决的问题在于:如何可以让一个代理类满足于所有的业务接口操作要求。

动态代理设计模式

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

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

image.png
动态代理设计模式

在进行动态代理实现的操作中,首先需要关注的就是一个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;
  • 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()方法,会发现该方法会使用大量的底层机制来进行代理对象的动态创建,所有的代理类是符合所有相关功能需求的操作功能类,它不再代表具体的接口,这样在处理时就必须依赖于类加载器与接口进行代理对象的伪造。

想学习更多的Java的课程吗?从小白到大神,从入门到精通,更多精彩不容错过!免费为您提供更多的学习资源。
本内容视频来源于阿里云大学

下一篇:CGLIB实现代理设计模式 | 带你学《Java语言高级特性》之九十六
更多Java面向对象编程文章查看此处

相关文章
|
19天前
|
存储 缓存 Java
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
71 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
|
4月前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
2月前
|
Oracle Java 关系型数据库
Java基础(一):语言概述
Java基础(一):语言概述
61 15
Java基础(一):语言概述
|
13天前
|
设计模式 中间件 Java
设计模式3:代理、适配器、装饰器模式
代理模式是一种结构型设计模式,通过中间件解耦服务提供者和使用者,使使用者间接访问服务提供者,便于封装和控制。
38 2
|
19天前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
66 5
|
2月前
|
存储 监控 算法
探秘局域网桌面监控:深入剖析 Java 语言核心算法
在数字化办公时代,局域网桌面监控如同企业的“智慧鹰眼”,确保工作效率与数据安全。本文以Java为载体,揭示哈希表在监控中的关键应用。通过高效的数据结构和算法,哈希表能快速索引设备连接信息,大幅提升监控的时效性和响应速度。代码示例展示了如何用Java实现设备网络连接监控,结合未来技术如AI、大数据,展望更智能的监控体系,助力企业在数字化浪潮中稳健前行。
|
4月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
4月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
62 4
|
4月前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
76 4
|
4月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
130 0