Java基础学习: 代理模式(Proxy Pattern)

文章目录

  • 一、简介
    • 1、介绍
    • 2、代理模式在Java中的应用
  • 二、实现方式
    • 1、静态代理
    • 2、动态代理
  • 三、动态代理
    • 1、JDK
    • 2、Cglib
    • 3、总结
  • 参考

一、简介

1、介绍

代理模式

2、代理模式在Java中的应用

  • 统一异常处理。
  • Mybatis使用了代理。
  • Spring aop实现代理。
  • 日志框架。

二、实现方式

1、静态代理

在Java中,静态代理是一种代理模式,它涉及为另一个对象(目标对象)提供一个代理对象,并由代理对象控制对目标对象的访问。这种代理模式在编译时就已经确定代理类,因此被称为“静态代理”。

静态代理通常包含以下角色:

  • 目标对象(Target):需要被代理的真实对象。
  • 代理对象(Proxy):持有目标对象的引用,并控制对目标对象的访问。代理对象与目标对象实现了相同的接口(或在Java中,它们可能是同一个类的子类)。
  • 接口(Interface):定义了目标对象和代理对象都需要实现的方法。

静态代理的基本实现步骤

  • 定义一个接口,该接口声明了目标对象与代理对象共有的方法。
  • 创建目标对象,实现接口并定义真实业务逻辑。
  • 创建代理对象,同样实现该接口,并在方法内部调用目标对象的方法,同时可以在调用前后添加额外的逻辑。
  • 客户端代码通过代理对象来调用目标对象的方法。

示例代码

// 接口  
public interface UserService {  void doSomething();  
}  // 目标对象  
public class UserServiceImpl implements UserService {  @Override  public void doSomething() {  System.out.println("执行真正的业务逻辑");  }  
}  // 代理对象  
public class UserServiceProxy implements UserService {  private UserService userService;  public UserServiceProxy(UserService userService) {  this.userService = userService;  }  @Override  public void doSomething() {  System.out.println("在目标方法执行前执行的逻辑");  userService.doSomething();  System.out.println("在目标方法执行后执行的逻辑");  }  
}  // 客户端代码  
public class Client {  public static void main(String[] args) {  UserService userService = new UserServiceImpl();  UserService proxy = new UserServiceProxy(userService);  proxy.doSomething(); // 调用代理对象的方法,实际上执行了目标对象的方法,并添加了额外逻辑  }  
}

静态代理灵活性较差,每当接口增加或修改方法时,代理类也需要相应地进行修改。对于不同的接口,需要编写不同的代理类,这可能导致“类爆炸”的问题。

2、动态代理

动态代理 是一种在运行时动态地创建代理类及其实例的技术。与静态代理不同,动态代理不需要手动编写代理类的代码,而是在运行时根据目标对象的接口或父类动态地生成代理类的字节码,并加载到JVM中,然后创建代理类的实例。这种代理方式的优点在于其高度的灵活性和可扩展性。

在Java中,实现动态代理主要有两种方式

  • JDK动态代理:基于Java的反射机制实现。JDK动态代理要求目标对象必须实现一个或多个接口,因为代理类是通过继承java.lang.reflect.Proxy类并实现与目标对象相同的接口来创建的。因此,JDK动态代理主要用于对接口进行代理。
  • CGLIB动态代理:基于ASM(一个通用的Java字节码操作和分析框架)库实现对类的字节码操作。与JDK动态代理不同,CGLIB动态代理是通过继承目标类来创建代理类的,因此它主要用于对没有实现接口的类进行代理。由于CGLIB是通过继承目标类来创建代理的,因此不能代理final类(因为final类不能被继承),同时目标类中的final方法也会被忽略(因为final方法不能被重写)。

动态代理的主要应用场景包括AOP(面向切面编程)、远程方法调用(RMI)等。在这些场景中,动态代理可以方便地为目标对象添加额外的功能(如日志记录、性能监控、事务管理等),而无需修改目标对象的代码。

三、动态代理

1、JDK

JDK动态代理

2、Cglib

CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,它可以在运行时扩展Java类和实现接口,而无需修改字节码。CGLIB被广泛用于AOP(面向切面编程)框架中,如Spring AOP,以在运行时动态地创建代理对象。

CGLIB与JDK动态代理的区别

  • JDK动态代理:基于接口实现,代理类必须是某个接口的实现。通过反射机制生成代理类的class字节码,并将其加载到Java虚拟机中。然后基于该接口动态生成代理实例,在调用具体方法前调用InvokeHandler来处理。
  • CGLIB动态代理:基于类实现,代理类继承被代理类(通过字节码技术继承)。CGLIB动态代理利用ASM库来转换字节码并生成新的类,比使用Java反射API生成代理类的速度更快。

CGLIB动态代理的工作原理

  • 创建Enhancer对象:Enhancer是CGLIB的核心类,用于创建一个子类对象(即代理对象)。
  • 设置回调函数:通过Enhancer的setCallback()或setCallbacks()方法设置当调用代理对象方法时被调用的方法。
  • 创建代理对象:通过Enhancer的create()方法创建代理对象。
  • 调用代理对象的方法:当调用代理对象的方法时,会先调用Enhancer中设置的回调函数(Callback),然后再调用被代理对象的方法。

CGLIB动态代理的示例

import net.sf.cglib.proxy.Enhancer;  
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  
import java.lang.reflect.Method;  public class CglibProxyDemo {  public static void main(String[] args) {  // 创建Enhancer对象,用于创建目标类的子类  Enhancer enhancer = new Enhancer();  // 设置父类,即目标类  enhancer.setSuperclass(RealSubject.class);  // 设置回调函数  enhancer.setCallback(new MethodInterceptor() {  @Override  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {  // 在调用目标方法之前执行的操作  System.out.println("Before method " + method.getName());  // 调用目标方法  Object result = proxy.invokeSuper(obj, args);  // 在调用目标方法之后执行的操作  System.out.println("After method " + method.getName());  return result;  }  });  // 创建代理对象  RealSubject proxyObj = (RealSubject) enhancer.create();  // 调用代理对象的方法  proxyObj.doSomething();  }  // 目标类  static class RealSubject {  public void doSomething() {  System.out.println("RealSubject: doSomething");  }  }  
}

在这个示例中,我们使用了CGLIB来创建一个RealSubject类的子类(即代理类),并在调用doSomething()方法时添加了额外的操作(打印方法调用前后的日志)。

3、总结

参考

  • https://www.bilibili.com/video/BV1tY411Z799/?p=2&spm_id_from=pageDriver&vd_source=cd03889ff27e1a185b3e97e3ed96d260

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/19957.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

位置参数

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 位置参数也称必备参数,是必须按照正确的顺序传到函数中,即调用时的数量和位置必须和定义时是一样的。 (1&#x…

使用 Docker 和 Docker Compose 部署 Vue

使用 Docker 和 Docker Compose 部署 Vue 项目有两种方式:直接使用 Docker 和使用 Docker Compose。 创建 Dockerfile 在Vue.js项目根目录下创建一个 Dockerfile 的文件 # 使用最新的官方 Node.js 镜像作为基础镜像,并命名为 builder 阶段 FROM node:…

内测:ew0.0版本

温馨提示&#xff1a;懒得编&#xff0c;可能会存在一点点bug。 合作请私信我&#xff0c;周六日有空。 合作对象&#xff1a;小学生&#xff0c;初中生不等。 #include<bits/stdc.h> #include<windows.h> using namespace std; void sprintf(string s){int len…

stack和queue(1)

一、stack的简单介绍和使用 1.1 stack的介绍 1.stack是一种容器适配器&#xff0c;专门用在具有先进后出&#xff0c;后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入和弹出操作。 2.stack是作为容器适配器被实现的&#xff0c;容器适配器即是…

信号与槽函数的魔法:QT 5编程中的核心机制

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、信号与槽函数的基本概念 二、信号与槽函数的实现原理 三、信号与槽函数的代码实例 四…

搭载算能 BM1684 芯片,面向AI推理计算加速卡

搭载算能 BM1684 芯片&#xff0c;是面向AI推理的算力卡。可集成于服务器、工控机中&#xff0c;高效适配市场上所有AI算法&#xff0c;实现视频结构化、人脸识别、行为分析、状态监测等应用&#xff0c;为智慧城市、智慧交通、智慧能源、智慧金融、智慧电信、智慧工业等领域进…

实用软件分享---- i茅台 在windows上自动预约和自动获取小茅运的软件

专栏介绍:本专栏主要分享一些实用的软件(Po Jie版); 声明1:软件不保证时效性;只能保证在写本文时,该软件是可用的;不保证后续时间该软件能一直正常运行;不保证没有bug;如果软件不可用了,我知道后会第一时间在题目上注明(已失效)。介意者请勿订阅。 声明2:本专栏的…

计算机基础学习路线

计算机基础学习路线 整理自学计算机基础的过程&#xff0c;虽学习内容众多&#xff0c;然始终相信世上无难事&#xff0c;只怕有心人&#xff0c;期间也遇到许多志同道合的同学&#xff0c;现在也分享自己的学习过程来帮助有需要的。 一、数据结构与算法 视频方面我看的是青…

C++_list简单源码剖析:list模拟实现

文章目录 &#x1f680;1. ListNode模板&#x1f680;2. List_iterator模板(重要)&#x1f331;2.1 List_iterator的构造函数&#x1f331;2.2 List_iterator的关于ListNode的行为 &#x1f680;3. Reverse_list_iterator模板(拓展)&#x1f680;4. List模板(核心)&#x1f331…

NVM:Node版本管理切换 vue ‘cnpm‘ 不是内部或外部命令,也不是可运行的程序

nvm使用&#xff1a; Node 多版本管理_node版本管理_骑士梦的博客-CSDN博客 node.js 安装及配置环境变量只看此文_node环境变量设置-CSDN博客 # 安装11.13.0版本。 nvm install 11.13.0# 显示已安装的Node版本列表&#xff08;list可简化为ls&#xff09;。 nvm list# 切换1…

【计算机毕设】基于SpringBoot的房产销售系统设计与实现 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 随着房地产市场的发展和互联网技术的进步&#xff0c;传统的房产销售模式逐渐向线上转移。设计并实现一个基于Spring Boot的房产销售系统&#xff0…

SpringCloud学习笔记(一)

SpringCloud、SpringCloud Alibaba 前置知识&#xff1a; 核心新组件&#xff1a; 所用版本&#xff1a; 学习方法&#xff1a; 1.看理论&#xff1a;官网 2.看源码&#xff1a;github 一、微服务理论知识 二、关于SpringCloud各种组件的停更/升级/替换 主业务逻辑是&#x…

尝试用智谱机器人+知识库,制作pytorch测试用例生成器

尝试用智谱机器人知识库,制作pytorch测试用例生成器 1 保存pytorch算子文档到txt2 创建知识库3 创建聊天机器人4 测试效果5 分享 背景:是否能将API的接口文档和sample放到RAG知识库,让LLM编写API相关的程序呢 小结:当前的实验效果并不理想,可以生成代码,但几乎都存在BUG 1 保存…

LeetCode:2965.找出缺失和重复的数字(hash Java)

目录 2965.找出缺失和重复的数字 题目描述&#xff1a; 实现代码与解析&#xff1a; hash 原理思路&#xff1a; 2965.找出缺失和重复的数字 题目描述&#xff1a; 给你一个下标从 0 开始的二维整数矩阵 grid&#xff0c;大小为 n * n &#xff0c;其中的值在 [1, n2] 范围…

星闪在智能汽车端的应用

随着智能汽车、智能终端、智能家居和智能制造等多产业的快速发展&#xff0c;多应用领域对无线短距通信技术在低延时、高可靠、低功耗等方面提出共性要求&#xff0c;现有主流无线短距通信技术的先天局限和技术潜力无法满足新应用的技术要求&#xff0c;针对解决行业技术痛点的…

StrApi基本使用

1.创建项目(这里只使用默认的sqllite) 点击链接进入官网查看先决条件,看看自己的node,python等是否符合版本要求 运行以下命令进行创建项目(网慢导致下载失败的话可以尝试使用手机热点给电脑使用,我就是这样解决的,也可以看我csdn的资源这里进行下载) yarn create strapi-ap…

智能化改造的关键点

1. 自动化与信息化的结合&#xff1a;通过自动化设备和信息化系统的结合&#xff0c;实现生产过程的自动化控制和数据管理。 2. 系统集成&#xff1a;将企业内部的各种系统&#xff08;如ERP、MES、PLM等&#xff09;进行有效集成&#xff0c;实现数据的流通和共享。 3. 精益…

力扣 264. 丑数 II python AC

堆 from heapq import heappop, heappushclass Solution:def nthUglyNumber(self, n):q [1]vis {1}for _ in range(n - 1):now heappop(q)for i in [2, 3, 5]:if now * i not in vis:vis.add(now * i)heappush(q, now * i)return heappop(q)

零基础学会asp.net做AI大模型网站/小程序之六:实战初体验(网站控件详解--基础控件及使用教学1)

关注我,持续分享逻辑思维&管理思维&面试题; 可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导; 博主在互联网大厂深耕近二十年,从一线码农做起,到人工智能公司副总裁。希望把过往经验总结出来,帮助到更多同学。有兴趣可关注博主后加个人微信(平台规定文章…

5.25.1 用于组织病理学图像分类的深度注意力特征学习

提出了一种基于深度学习的组织病理学图像分类新方法。我们的方法建立在标准卷积神经网络 (CNN) 的基础上,并结合了两个独立的注意力模块,以实现更有效的特征学习。 具体而言,注意力模块沿不同维度推断注意力图,这有助于将 CNN 聚焦于关键图像区域,并突出显示判别性特征通…