Spring代理模式——静态代理和动态代理

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:SSM 框架从入门到精通
✨特色专栏:国学周更-心性养成之路
🥭本文内容:Spring代理模式——静态代理和动态代理
文章目录
- 代理模式
- 1、静态代理
- 2、动态代理
代理模式
在学习 AOP 之前,我们先来了解下代理模式, 代理模式分为静态代理以及动态代理,属于23中设计模式之一。 AOP 的底层机制就是动态代理。

作用:
通过代理类为原始类增加额外的功能
1、静态代理
1)案例展示
【1】定义一个 Teacher 接口,接口中定义两个方法:teachOnLine 和 teachOffLine。
package cn.gc.spring03.interfce;public interface Teacher {String teachOnLine(String course);String teachOffLine(String course);
}
【2】定义一个实现 Teacher 接口的 TeacherA 实现类,代码如下:
package cn.gc.spring03.interfce.impl;import cn.gc.spring03.interfce.Teacher;public class TeacherA implements Teacher {@Overridepublic String teachOnLine(String course) {System.out.println("开始"+course+"课程线上教学");return course+"课程线上教学";}@Overridepublic String teachOffLine(String course) {System.out.println("开始"+course+"课程线下教学");return course+"课程线下教学";}
}
【3】现在我们要在两个方法中的 开始课程教学 的前后添加上下课铃声的功能,此时我们再定义一个实现 Teacher 接口的静态代理类 TeacherAStaticProxy,代码如下:
package cn.gc.spring03.proxy;import cn.gc.spring03.interfce.Teacher;
import cn.gc.spring03.interfce.impl.TeacherA;public class TeacherAStaticProxy implements Teacher {TeacherA teacherA=new TeacherA();@Overridepublic String teachOnLine(String course) {System.out.println(course+"课程上课时间到了");String s = teacherA.teachOnLine(course);System.out.println(course+"课程下课时间到了");return s;}@Overridepublic String teachOffLine(String course) {System.out.println(course+"课程上课时间到了");String s = teacherA.teachOffLine(course);System.out.println(course+"课程下课时间到了");return s;}
}
【4】运行效果如下

2)静态代理优缺点
(1)优点 :在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展;可以使得真实角色更加纯粹,不再去关注一些公共的事情;公共的业务由代理来完成,实现了业务的分工。
(2)缺点 :因为代理对象需要与目标对象实现一样的接口,所以会很多代理类 ,一旦接口增加方法,目标对象与代理对象都要维护,工作量变大,开发效率降低。
3)开发代理对象的原则
-
代理对象和目标对象实现相同的接口
-
代理对象依赖于目标对象
2、动态代理
在不改变原来的代码的情况下,实现了对原有功能的增强,这是 AOP 中最核心的思想。
AOP:纵向开发,横向开发

1)简介
动态代理的角色和静态代理的一样。但是动态代理的代理类是动态生成的,而静态代理的代理类是提前写好的。
动态代理分为两类,一类是基于接口动态代理(JDK),一类是基于类的动态代理(CGLib)。
2)基于接口动态代理(JDK)
程序运行的过程中,通过 JDK 提供代理技术动态的为某个类产生动态代理对象的过程。
开发代理对象的原则:
- 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用JDK动态代理。
- 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象。
- 动态代理也叫做 :JDK代理、接口代理。
JDK 的动态代理需要了解两个类:
- 核心 : InvocationHandler (调用处理程序) 和 Proxy (代理)

实现步骤:在上面案例的基础上实现。
创建一个基于 JDK 的代理工具类 DynamicProxy 类:
package cn.gc.spring03.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/** 基于JDK的代理工具类*/
public class DynamicProxy {//被代理对象private Object target;public DynamicProxy(Object obj) {this.target = obj;}//生成代理对象public Object getProxy() {//获取类加载器ClassLoader classLoader = target.getClass().getClassLoader();//获取被代理对象实现的所有接口Class<?>[] interfaces = target.getClass().getInterfaces();//增强功能代码编写的位置InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 增强的功能System.out.println(args[0] + "课程上课时间到了");// 通过反射执行目标方法Object invoke = method.invoke(target, args);// 增强的功能System.out.println(args[0] + "课程下课时间到了");return invoke;}};Object o = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);return o;}
}
测试:
@Testpublic void test02() {Teacher teacher = new TeacherA();DynamicProxy dynamicProxy = new DynamicProxy(teacher);Teacher teacherProxy = (Teacher) dynamicProxy.getProxy();teacherProxy.teachOnLine("Java");System.out.println("______________________");teacherProxy.teachOnLine("C++");}
运行效果:

3)基于类的动态代理(CGLib)
开发代理对象的原则:
-
代理对象无需和原始类对象实现相同的接口
-
代理对象和原始类对象要存在父子类关系
CGLib 的动态代理需要了解两个类:
- 核心 : Enhancer 和 MethodInterceptor
实现步骤
创建一个 Aoo 类:
package cn.gc.spring03.interfce.impl;public class Aoo {public String test01(String info){System.out.println("Aoo中的test01方法被调用。");return info;}
}
创建一个基于 CGLib 的代理工具类 CglibProxy 类:
package cn.gc.spring03.proxy;import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CglibProxy {private Object target;public CglibProxy(Object obj){this.target=obj;}public Object getProxy(){Enhancer enhancer=new Enhancer();//设置类加载器enhancer.setClassLoader(CglibProxy.class.getClassLoader());//设置被代理对象enhancer.setSuperclass(target.getClass());//增强功能代码编写的位置MethodInterceptor methodInterceptor=new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("-------------cglib log--------------");Object invoke = method.invoke(target, objects);System.out.println("-------------cglib log--------------");return invoke;}};enhancer.setCallback(methodInterceptor);//代理对象Object o = enhancer.create();return o;}
}
测试:
@Testpublic void test03() {Aoo aoo=new Aoo();CglibProxy cglibProxy = new CglibProxy(aoo);Aoo proxy = (Aoo) cglibProxy.getProxy();String info = proxy.test01("java");System.out.println("info = " + info);}
运行效果:

4)动态代理的优势
- 可以使得真实角色更加纯粹,不再去关注一些公共的事情。
- 公共的业务由代理来完成,实现了业务的分工。
- 公共业务发生扩展时变得更加集中和方便。
- 一个动态代理,一般代理某一类业务。
- 一个动态代理可以代理多个类,代理的是接口。

码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识,点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

相关文章:
Spring代理模式——静态代理和动态代理
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
Anaconda和PyCharm的一些安装问题和命令
今天更新了Windows上的Anaconda到2.3.2,PyCharm到2022.3。 ——发现是纯纯的犯贱orz。出了一堆问题。在这里记录一下供后来者参考。 Anaconda安装 将.\anaconda3\Scripts 和.\anaconda3\Library\bin添加到系统环境变量中。 新建环境的目录在.\anaconda3\envs下 N…...
sql优化建议
对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 应尽量避免在 where 子句中使用!或<>操作符,否则将引擎放弃使用索引而进行全表扫描。 应尽量避免在 where 子句中对字段进行 null 值判断&a…...
google hacker语句
哎,我就是沾边,就是不打实战( ̄o ̄) . z Z 文章目录前言一、什么是谷歌Docker?二、受欢迎的谷歌docker语句谷歌docker的例子日志文件易受攻击的 Web 服务器打开 FTP 服务器SSH私钥电子邮件列表实时摄像机MP3、电影和 PDF…...
Spring AOP
Spring AOP 文章目录Spring AOP1.概念1.面向切面编程2.AOP的目的3.AOP实现的分类4.AOP 术语2. Spring AOP的特性1.能力与目标2.AOP机制1.理解SpringAOP的代理2.AOP代理类的自调用代码的粒度如何让自调用走代理?3.Enabling AspectJ Support3. 定义切面与切点1. 声明切…...
【消费战略方法论】认识消费者的恒常原理(一):消费者稳态平衡原理
“消费战略”是塔望咨询基于大量的战略与营销实践经验结合心理学、经济学、传播学等相关专业学科的知识应用进行提炼与创造形成的战略方法体系。消费战略强调以消费者为导向,进行企业、品牌战略、品牌营销的制订和落地,企业经营的每个环节和输出的每个动…...
python居然能语音控制电脑壁纸切换,只需60行代码
前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 家在日常的电脑使用中,都会有自己喜爱类型的桌面 单纯的桌面有时候会让人觉得单调 今天,就由我带领大家只用60行代码打造一款语音壁纸切换器程序, 让大家能够通过语音的方式来控制电脑去…...
内存泄露定位手段(c语言hook malloc相关方式)
如何确定有内存泄露问题,如何定位到内存泄露位置,如何写一个内存泄漏检测工具? 1:概述 内存泄露本质:其实就是申请调用malloc/new,但是释放调用free/delete有遗漏,或者重复释放的问题。 内存…...
STM32 CAN波特率计算
STM32 CAN波特率计算简介CAN总线收发,中断方式接收配置代码部分reference简介 CAN通信帧共分为数据帧、远程帧、错误帧、过载帧和帧间隔,本文这里以数据帧为例。 显性电平对应逻辑0,CAN_H和CAN_L之差为2.5V左右。而隐性电平对应逻辑1&#x…...
C/C++ 中#define 的妙用,让代码更美一些
C/C 中#define 的妙用,让代码更美一些 flyfish 1 数值类型输出易读的字符串形式 例如使用enum定义一些错误值,想要将数值类型的错误,输出易读的字符串形式 重要的一句代码 #define MAKE_PAIR(val) std::make_pair(val, #val)可以看到 #va…...
Linux文件系统操作与磁盘管理
查看磁盘和目录的容量 使用 df 命令查看磁盘的容量 df在实验楼的环境中你将看到如下的输出内容: 但在实际的物理主机上会更像这样: 物理主机上的 /dev/sda2 是对应着主机硬盘的分区,后面的数字表示分区号,数字前面的字母 a 表示…...
【Python】批量采集原神表情包~
嗨害大家好鸭~我是小熊猫(✿◡‿◡) 最近迷上了原神, 不自觉中就很喜欢保存广大旅行者制作的表情包~ 真的很有意思诶~ 源码资料电子书:点击此处跳转文末名片获取 一个个保存的话,好像效率很低嘛… 那我就发挥我小熊猫的老本行直接给把他们全部采集下…...
C语言基本语法注释类型关键字
C 基本语法 标识符 给变量所取的名字叫变量名,定义变量的名字需要遵循标识符的命名规则。 标识符是用来标识变量、符号常量、数组、函数、文件等名字的有效字符序列。 标识符的命名规则: 1.只能由字母、数字和下划线组成(例如:…...
【C ++】C++入门知识(二)
C入门(二) 作者:小卢 专栏:《C》 喜欢的话:世间因为少年的挺身而出,而更加瑰丽。 ——《人民日报》 1.引用 1.1.引用的概念及应用 引用(&) 引用不是新定义一个变量࿰…...
qt qchart学习
Qt Charts主要由QChartView、QChart、QLegend图例、坐标轴(由QAbstractAxis子类实现)、**数据源(由QAbstractSeries子类实现)**等组成使用QChart的前期准备1. Qt5.9及以上版本;2. .pro文件中添加QT charts3. 在使用QChart的各个控件之前,引用头文件并必…...
手工布署 java 项目
新建一个java springboot项目 maven 这是一个非常简易的 springBoot 的项目 使用 maven 的 package 工具进行打包 把包上传到 linux 的机器上, 确保 linux 机器上安装了 java jdk工具, 并且配置好了 JAVA_HOME 注意,helloworld 默认的是要使…...
《设计模式》观察者模式
《设计模式》观察者模式 观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象可以同时监听和相应被观察者对象的状态变化,以达到解耦和复用的目的。观察者模式的优点如下: 解耦:观察者模…...
基于SpringBoot的外卖项目(详细开发过程)
基于SpringBootMyBatisPlus的外卖项目1、软件开发整体介绍软件开发流程角色分工2、外卖项目介绍项目介绍产品展示后台系统管理移动端技术选型功能结构角色3、开发环境的搭建开发环境说明建库建表Maven项目搭建项目的目录结构pom.xmlapplication.ymlReggieApplication启动类配置…...
ChatGPT 研发传言席卷互联网公司,这会是一门好生意吗?
ChatGPT(也称GPT-3)是一种基于人工智能的自然语言生成模型,由OpenAI团队开发。它是GPT系列模型的最新版本,于2020年6月发布。ChatGPT的由来GPT-1是在2018年发布的第一个版本,使用了12亿个参数。随后,GPT-2在…...
获取servlet转发和响应重定向的方式是什么?
(1) 重定向和转发的区别 1)重定向是浏览器发送请求并受到响应以后再次向一个新地址发请求;转发是服务器受到请求后为了完成响应转到一个新的地址。 2)重定向中有两次请求对象,不共享数据;转发…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
