Spring:代理模式

article/2025/10/2 6:19:39

一、概述

        代理模式分为静态代理以及动态代理,属于23中设计模式之一。动态代理是SpringAop的底层。代理的概念如下图所示:

二、 静态代理

上图角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真是角色:被代理的角色
  • 代理角色:代理真是角色,代理真是角色后,一般会做一些附属操作。

示例1:上图代码实现如下:

对出租房屋进行抽象(接口):

/*** 抽象角色:租房*/
public interface Rent {public void rent();
}

Host.java 真实角色:

/*** 真是角色:房东,房东要出租房屋*/
public class Host implements Rent{@Overridepublic void rent() {System.out.println("房东出租房屋");}
}

Proxy . java 即代理角色

/*** 代理角色,中介*/
public class Proxy implements Rent {private Host host;public Proxy(){}public Proxy(Host host){this.host = host;}@Overridepublic void rent() {seeHouse();host.rent();fare();}/*** 看房,属于代理类增加的逻辑*/public void seeHouse(){System.out.println("带客户看房");}/*** 收费,属于代理类增加的逻辑*/public void fare(){System.out.println("收费");}
}

客户:

    /*** 租房:静态代理*    客户会去找代理,由代理提供相应服务,其中的核心服务被代理类包裹*/@Testpublic void TestDaili(){//房东出租房Host host = new Host();//中介包裹房东Proxy proxy = new Proxy(host);//客户找代理(中介)租房proxy.rent();;}

代理模式的优点:

  • 可以使真实角色的操作更加纯粹!不用关注一些公共的业务。
  • 公共业务交给代理角色,实现了业务的分工
  • 公共业务扩展的时候,方便集中管理。

静态代理的缺点:

  • 一个真实角色就会产生一个代理角色,代码量翻倍,开发效率变低。

示例2:代理增加日志功能

1. 创建一个抽象接口,对用户业务进行抽象:

/*** 抽象角色:增、删、改、查*/
public interface UserService {void add();void delete();void update();void query();
}

2. 创建真实对象,实现以上业务

/*** 真实角色:完成UserService*/
public class UserServiceImpl implements UserService{@Overridepublic void add() {System.out.println("增加一个用户");}@Overridepublic void delete() {System.out.println("删除一个用户");}@Overridepublic void update() {System.out.println("更新一个用户");}@Overridepublic void query() {System.out.println("查询一个用户");}
}

        此时,业务代码是可以正常运行的,现在,我们有一个新的需求:实现一个日志输出功能,以记录业务代码的调用情况。实现思路有两种,如下:

  • 思路1:在业务实现类每个方法中增加相应操作(该思路是传统方法,缺点很多)。
  • 思路2:使用代理,在不改变原有业务的情况下,实现此日志记录功能!

3. 创建代理类

/*** 代理角色,在代理业务原有功能的同时,增加日志输出*/
public class UserServiceProxy implements UserService{private UserServiceImpl userService; //被代理的业务对象public void setUserService(UserServiceImpl userService){this.userService = userService;}@Overridepublic void add() {log("add");userService.add();}@Overridepublic void delete() {log("delete");userService.delete();}@Overridepublic void update() {log("update");userService.update();}@Overridepublic void query() {log("query");userService.query();}/*** 日志输出功能* @param msg*/public void log(String msg){System.out.println("执行了"+msg+"方法");}
}

4. 测试

public class client {public static void main(String[] args) {//真实业务UserServiceImpl userService = new UserServiceImpl();//代理类UserServiceProxy proxy = new UserServiceProxy();//代理类注入被代理对象proxy.setUserService(userService);proxy.add();}
}

        以上示例1及示例2代码都是为了体现一个重要的思想:在不改变原有代码的情况下,实现对原有功能的增强。这是AOP中最核心的思想,如下图所示:

 三、动态代理

        动态代理和静态代理的角色是一样的,动态代理的代理类是动态生成的,不是像静态代理那样是直接写死的。动态代理可以分为两大类:一类是基于接口动态代理 , 一类是基于类的动态代理。

  • 基于接口的动态代理,如JDK动态代理
  • 基于类的动态代理,如cglib

JDK的动态代理需要了解两个类

        核心 : InvocationHandler (调用处理程序)    和     Proxy (代理)

InvocationHandler调用处理程序)

//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。

Object invoke(Object proxy, 方法 method, Object[] args)

 Proxy:代理

动态代理类 是一个实现在类创建时在运行时指定的接口列表的类,具有如下所述的行为。 代理接口是由代理类实现的接口。 代理实例是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序对象,它实现了接口InvocationHandler 。 通过其代理接口之一的代理实例上的方法调用将被分派到实例调用处理程序的invoke方法,传递代理实例, java.lang.reflect.Method被调用方法的java.lang.reflect.Method对象以及包含参数的类型Object Object的数组。 调用处理程序适当地处理编码方法调用,并且返回的结果将作为方法在代理实例上调用的结果返回。

生成代理类的方法(静态方法): 

//生成代理类
public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}

示例:

1. 通用的动态代理实现类:

public class ProxyInvocationHandler implements InvocationHandler {private Object target; //被代理对象public void setTarget(Object target) {this.target = target;}/*** 生成代理类* @return*/public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}/**** @param proxy 代理类* @param method 代理类的调用处理程序的方法对象* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {log(method.getName());Object result = method.invoke(target,args);return  result;}public void log(String methodName){System.out.println("执行了"+methodName+"方法");}
}

2. 测试:

public class Client {public static void main(String[] args) {//真实对象UserServiceImpl userService = new UserServiceImpl();//代理对象的调用处理程序ProxyInvocationHandler pih = new ProxyInvocationHandler();/*** 设置要代理的对象*/pih.setTarget(userService);//动态生成代理类UserService proxy = (UserService) pih.getProxy();proxy.delete();}
}

动态代理的优点:

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .

  • 公共的业务由代理来完成 . 实现了业务的分工 ,

  • 公共业务发生扩展时变得更加集中和方便 .

  • 一个动态代理 , 一般代理某一类业务

  • 一个动态代理可以代理多个类,代理的是接口

四、Spring AOP操作 示例

        AOP操作概述:https://blog.csdn.net/sssxlxwbwz/article/details/122776028 

 示例:

        业务抽象接口:

public interface UserService {public void add();public void delete();public void update();public void search();
}

        业务实现类:

public class UserServiceImpl implements UserService{@Overridepublic void add() {System.out.println("增加用户");}@Overridepublic void delete() {System.out.println("删除用户");}@Overridepublic void update() {System.out.println("更新用户");}@Overridepublic void search() {System.out.println("查询用户");}
}

        编写切入类:

public class DiyPointcut {public void before(){System.out.println("===方法执行前===");}public void after(){System.out.println("===方法执行后===");}
}

        Spring配置文件中进行AOP配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 注册Bean --><bean id="userService" class="com.wyf.service.UserServiceImpl"/><!-- 配置AOP 需要导入AOP约束 --><!-- 自定义类注册 --><bean id="diy" class="com.wyf.pointcut.DiyPointcut"/><aop:config><!-- 将上面的自定义类定义为切面,切面包含切点和通知 --><aop:aspect ref="diy"><!-- 切入点 --><aop:pointcut id="point" expression="execution(* com.wyf.service.UserServiceImpl.*(..))"/><!-- 通知,表明什么时候执行什么方法,以及作用到的切入点 --><aop:before method="before" pointcut-ref="point"/><aop:after method="after" pointcut-ref="point"/></aop:aspect></aop:config></beans>

测试类:

public class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = (UserService) context.getBean("userService");userService.search();}
}


http://chatgpt.dhexx.cn/article/m3ueVAKq.shtml

相关文章

什么是代理模式,如何写一个代理模式

什么是代理模式 代理模式分为静态代理模式&#xff0c;和动态代理模式&#xff0c;代理模式就是创建一个代理对象&#xff0c;由代理对象来接管原对象的引用,静态代理模式需要让代理类和被代理的类实现同一个接口&#xff0c;通过代理类中定义的构造方法将被代理的对象作为参数…

代理模式(Proxy)

代理模式介绍 代理模式:为一个对象提供一个替身&#xff0c;以控制对这个对象的访问。即通过代理对象访问目标对象好处是:可以在目标对象实现的基础上,增强额外的功能操作&#xff0c;即扩展目标对象的功能被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象代…

代理 模式

代理模式 Proxy Pattern 为其他对象提供一个代理以控制对这个对象的访问 可以详细控制访问某个&#xff08;某类&#xff09;对象的方法&#xff0c;在调用这个方法前做前置处理&#xff0c;调用这个方法后做后置处理。 静态代理 直接写死的代码的代理逻辑 动态代理 动态…

代理模式例子

1.概念 代理模式就是为某个对象提供一种代理&#xff0c;以控制对这个对象的访问。 2.涉及角色 抽象角色&#xff1a;声明真实对象和代理对象的共同接口&#xff1b; 代理角色&#xff1a;代理对象角色内部含有对真实对象的引用&#xff0c;从而可以操作真实对象&#xff…

代理模式的使用

一.代理模式 代理模式是java常用的设计模式。 代理的定义&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。 简单点说就是代理对象与实际对象都实现了相同的接口&#xff0c;我们可以通过代理对象来间接的访问实际对象&#xff0c;也因为这种间接性&#xff0c;我…

C++之代理模式

目录 模式思想 简介 组成 优点 代码实现 情景 如果不使用代理的话&#xff1a; 加代理的话&#xff1a; 结果 模式思想 简介 代理模式&#xff1a; 通过代理类&#xff0c;来控制实际对象的访问权限。 在某些情况下&#xff0c;一个对象不适合或者不能直接引用另…

代理模式与动态代理模式

原文地址&#xff1a;点击打开链接 1、代理模式 所谓代理&#xff0c;就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下&#xff0c;一个客户不想或者不能够直接引用一个对象&#xff0c;而代理对象可以在客户端和目标对象之前起到中介的作用。 代理模…

设计模式之代理模式(C++)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 一、代理模式是什么&#xff1f; 代理模式是一种结构型的软件设计模式&#xff0c;在不改变原代码前提下&#xff0c;提供一个代理…

动态代理模式详解

目录 &#xff08;一&#xff09;什么是动态代理模式 &#xff08;二&#xff09;动态代理模式入门案例 1.完成一个账户转账的功能 2. v1.0版本为转账添加一个事务 3.v2.0将事务从业务层和从持久层剥离 4.v3.0将事务使用动态代理完成 5.v3.0通过cglib实现代理模式 &…

三种代理模式详解

文章目录 二、代理模式&#xff08;Proxy Pattern&#xff09;1、常见的几种代理模式&#xff1a;2、静态代理3、JDK动态代理4、CGLib代理5、CGLib和JDK动态代理的区别 二、代理模式&#xff08;Proxy Pattern&#xff09; 根据B站狂神视频整理&#xff1a;https://www.bilibil…

Spring的代理模式

1、代理模式 为什么要学习代理模式&#xff1f; 因为这就是springAOP的底层&#xff01;【springAOP和springMVC】 代理模式的分类&#xff1a; 静态代理动态代理 1.1、静态代理 角色分析&#xff1a; 抽象角色&#xff1a;一般会使用接口或者抽象类来解决真实角色&…

代理模式(Proxy模式)详解

在有些情况下&#xff0c;一个客户不能或者不想直接访问另一个对象&#xff0c;这时需要找一个中介帮忙完成某项任务&#xff0c;这个中介就是代理对象。例如&#xff0c;购买火车票不一定要去火车站买&#xff0c;可以通过 12306 网站或者去火车票代售点买。又如找女朋友、找保…

代理模式的详细介绍

国庆期间闲来无事&#xff0c;写了一个简单的小程序&#xff0c;小程序名称叫做 IT藏经楼。目的是分享这些年自己积累的一些学习材料&#xff0c;方面大家查找使用&#xff0c;包括电子书、案例项目、学习视频、面试题和一些PPT模板。里面所有材料都免费分享。目前小程序中只发…

代理模式

代理模式 代理模式应用场景模式结构实现方式 代理模式 控制着对于原对象的访问&#xff0c; 并允许在将请求提交给对象前后进行一些处理。 优点&#xff1a; 在客户端与目标对象之间起到一个中介作用和保护目标对象的作用&#xff1b;代理对象可以扩展目标对象的功能&#x…

代理模式详解

1. 代理模式 代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问&#xff0c;这样就可以在不修改原目标对象的前提下&#xff0c;提供额外的功能操作&#xff0c;扩展目标对象的功能。 代理模式一半包含三种角色&#x…

代理模式详细讲解

文章目录 一、什么是代理模式&#xff1f;二、 为什么使用代理模式&#xff1f;三、 代理模式的实现1、静态代理1.1、 创建公共的接口1.2、 创建被代理角色1.3、 创建代理角色1.4、 创建测试类 2、动态代理的实现2.1、 使用 JDK 的 Proxy 类实现动态代理1、 创建业务接口2、 创…

一文搞懂代理模式

代理模式 前言一、代理模式是什么&#xff1f;二、静态代理三、动态代理1.jdk动态代理&#xff08;接口代理&#xff09;2.cglib动态代理 前言 一、代理模式是什么&#xff1f; 代理模式是常见的设计模式之一&#xff0c;顾名思义&#xff0c;代理模式就是代理对象具备真实对象…

手机测试耳机音质的软件,耳机音质测试软件有哪些

耳机音质测试软件并不存在&#xff0c;因为耳机的音质对于人来说是主观的&#xff0c;你认为音质好的耳机&#xff0c;有的人却并不认为也很正常&#xff0c;国内外都没有恒定的耳机音质评判标准&#xff0c;大多数人认为音质好的耳机&#xff0c;那么它十有八九实际就是好的。…

软件测试的基本理论与方法

文章目录 前言软件测试基础1. 软件测试的概念2. 软件测试的目的 测试用例1. 测试用例的概念2. 测试用例的分类3. 测试用例的治理4. 测试用例的编制及使用5. 测试需求 软件生命周期1. 问题的定义及规划2. 需求分析3. 软件设计4. 程序编码5. 软件测试6. 运行维护7. 生命周期模型 …

固态硬盘测试软件有哪些,SSD测试软件有哪些?SSD测试软件盘点

在购买了固态硬盘(SSD)后&#xff0c;如果对商家或官方给出的诸如读写速度等关键性数据存在质疑的话&#xff0c;最好的解决方法莫过于通过SSD测试软件来找寻答案。那么&#xff0c;SSD测试软件有哪些&#xff1f;SSD测试软件哪个比较好用呢&#xff1f;针对上述问题&#xff0…