t型布局网站/关键词排名怎样
1. 定义:代理对象和目标对象
1.1 目标对象(Target Object)
- 目标对象是指 被增强的原始对象,即需要通过 AOP 切面(Aspect)增强功能的业务对象(原始类)。
- 增强逻辑(Advice)最终是应用在目标对象的方法上的。
- 目标对象是实际的业务逻辑持有者,它的功能由我们开发时编写的类直接实现。
例子:
public class UserService {public void createUser() {System.out.println("Creating user...");}
}
UserService
是目标对象,定义了业务逻辑。
1.2 代理对象(Proxy Object)
- 代理对象是 Spring AOP 框架生成的 动态代理类实例,它是目标对象的增强版本。
- 代理对象会包装目标对象,并在执行目标对象方法时:
- 增加切面中的增强逻辑(如日志、事务等)。
- 将调用转发到目标对象的方法。
- 代理对象在 Spring 应用上下文中取代了目标对象,用户通过代理对象间接访问目标对象的功能。
代理对象的特点:
- 它的外部表现与目标对象相同(方法签名一致)。
- 它在方法调用时,可以插入增强逻辑(Advice)。
例子:
如果为 UserService
添加一个切面增强功能(例如日志记录),Spring 会生成一个代理对象来拦截方法调用。
UserService proxy = (UserService) context.getBean(UserService.class);
proxy.createUser();
2. 两者的区别
特性 | 目标对象(Target Object) | 代理对象(Proxy Object) |
---|---|---|
定义 | 原始的、未增强的业务对象 | Spring AOP 框架生成的动态代理对象 |
是否真实存在 | 是真实存在的类实例(用户定义的类) | 是由 Spring 动态生成的新实例 |
增强逻辑(Advice) | 不包含增强逻辑 | 包含增强逻辑,方法调用可能被拦截 |
访问方式 | 只能通过代理对象间接访问 | 直接被容器返回,外部调用的方法实际上由代理处理 |
与 Spring 的关系 | 原始业务逻辑的实现者 | 通过 Spring AOP 动态生成的代理实现 |
实际工作 | 执行被调用的具体业务方法 | 拦截方法调用,并决定是否执行增强逻辑或目标对象 |
反射行为 | 目标对象的方法是用户定义的,直接反射可访问 | 代理对象的方法是动态生成的,可能有额外逻辑 |
3. Spring 中是如何生成代理对象的
Spring AOP 中的代理对象生成有两种方式,分别基于 JDK 动态代理 和 CGLIB 动态代理。
代理的选择由目标对象的类型决定:
3.1 JDK 动态代理
- 使用 Java 提供的动态代理机制(
java.lang.reflect.Proxy
)。 - 要求目标对象实现一个或多个接口。
- 代理对象是目标对象实现的接口的一个实现类。
优点:
- 轻量级,直接基于接口生成代理。
缺点:
- 目标对象必须实现接口,如果是纯类无法使用。
示例:
public interface UserService {void createUser();
}public class UserServiceImpl implements UserService {@Overridepublic void createUser() {System.out.println("Creating user...");}
}
- Spring 会为
UserServiceImpl
生成一个动态代理对象,它实现了UserService
接口。
3.2 CGLIB 动态代理
- 使用 CGLIB(Code Generation Library)生成目标对象的子类作为代理对象。
- 不要求目标对象实现接口,可以代理普通的类。
- 代理对象是目标对象的子类,并通过方法重写(方法增强)来实现切面功能。
优点:
- 不需要目标对象实现接口,可以直接增强普通类。
缺点:
- 比 JDK 动态代理稍微重一些。
示例:
public class UserService {public void createUser() {System.out.println("Creating user...");}
}
- Spring 会为
UserService
生成一个代理子类,并在方法上织入切面逻辑。
3.3 Spring 如何选择代理方式
Spring 默认通过 JDK 动态代理生成代理对象。如果目标对象没有实现接口,则自动切换为 CGLIB 动态代理。
可以通过以下配置强制使用 CGLIB 动态代理:
@EnableAspectJAutoProxy(proxyTargetClass = true)
4. 代理对象和目标对象的实际差异
在 Spring AOP 的运行时动态代理中,外部用户调用的其实是代理对象而非目标对象。以下是一些细节差异:
4.1 方法调用流程
未增强(目标对象直接调用):
UserService userService = new UserService();
userService.createUser();
方法调用的流程:
- 直接调用目标对象的
createUser()
方法。 - 输出:
Creating user...
增强(通过代理对象调用):
UserService proxy = (UserService) context.getBean(UserService.class);
proxy.createUser();
方法调用的流程:
- 调用代理对象的
createUser()
方法。 - 代理对象拦截方法调用。
- 代理对象决定是否执行切面增强逻辑(如前置通知、后置通知等)。
- 代理对象将调用转发到目标对象的
createUser()
方法。
4.2 是否可以直接访问目标对象
-
直接通过 Spring 容器获取的 Bean 是代理对象:
Spring 容器会将代理对象注册为 Bean,用户通过@Autowired
或getBean()
获取的 Bean 实际上是代理对象。 -
通过 AOP 上下文访问目标对象:
如果需要直接访问目标对象(绕过代理),可以通过 Spring 提供的AopContext
:UserService target = (UserService) AopContext.currentProxy();
4.3 代理对象与目标对象的相互关系
-
代理对象包含目标对象:
代理对象会将对业务方法的调用最终转发给目标对象。 -
目标对象不知道代理对象的存在:
目标对象的代码完全独立,不需要感知代理对象或 Spring 的存在。
5. 示例:代理对象和目标对象的工作过程
目标对象
public class UserService {public void createUser() {System.out.println("Creating user...");}
}
切面
@Aspect
@Component
public class LoggingAspect {@Before("execution(* com.example.UserService.*(..))")public void logBefore() {System.out.println("Logging before method execution...");}
}
运行时流程
- Spring 生成一个代理对象(通过 JDK 动态代理或 CGLIB)。
- 用户调用代理对象的
createUser()
方法。 - 代理对象拦截该调用,并触发切面逻辑(前置通知)。
- 代理对象将方法调用转发给目标对象。
- 目标对象执行原始业务逻辑。
6. 总结
代理对象 | 目标对象 |
---|---|
Spring 动态生成的增强版本。 | 开发者定义的原始业务逻辑类。 |
包含切面逻辑(通知)。 | 不包含切面逻辑,只有业务逻辑。 |
用户通过代理对象间接访问目标对象方法。 | 仅通过代理对象间接调用。 |
可以插入增强逻辑(如日志记录、事务)。 | 无法直接应用增强逻辑。 |
相关文章:

代理对象与目标对象
1. 定义:代理对象和目标对象 1.1 目标对象(Target Object) 目标对象是指 被增强的原始对象,即需要通过 AOP 切面(Aspect)增强功能的业务对象(原始类)。增强逻辑(Advice…...

【Kubernetes Pod间通信-第3篇】Kubernetes中Pod与ClusterIP服务之间的通信
引言 我们之前了解了在不同场景下,Kubernetes中Pod之间的通信是如何路由的。 【Kubernetes Pod间通信-第1篇】在单个子网中使用underlay网络实现Pod到Pod的通信【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信现在,我们来看看在集群中,Pod与服务之间的通信是如何…...

DNN(深度神经网络)近似 Lyapunov 函数
import torch import torch.nn as nn import torch.optim as optim import matplotlib.pyplot as plt # from torchviz import make_dot import torchviz# 1. Lyapunov 函数近似器(MLP 结构) class LyapunovNet(nn.Module):def __init__(self, input_dim…...

128陷阱
首先我们了解一下关于包装器类型 java是面向对象的语言,但基本类型并不是面向对象的,从而出现了包装器类型,并且包装器添加了更多的属性和方法。如我们在使用集合类型Collection的时候就一定要使用包装类型而非基本类型,它相当于将…...

PromptSource和LangChain哪个更好
目录 1. 设计目标与定位 PromptSource LangChain 2. 功能对比 3. 优缺点分析 PromptSource LangChain 4. 如何选择? 5. 总结 PromptSource 和 LangChain 是两个在自然语言处理(NLP)领域非常有用的工具,但它们的设计目标和…...

构成正方形的数量:算法深度剖析与实践
目录 引言算法核心概念 定义正方形的构成条件数据结构与输入形式算法数学原理 几何关系的数学表达坐标运算与判定逻辑Python 实现 代码展示代码解析Python 实现的优势与局限C 语言实现 代码展示代码解析C 语言实现的性能特点性能分析与优化 性能分析 时间复杂度空间复杂度优化思…...

Redis持久化-秒杀系统设计
在构建高性能、高可用的系统时,Redis 作为缓存和消息队列的角色越来越重要。在一些场景下,我们还需要将 Redis 的数据进行持久化,以确保数据的安全性和恢复能力。除此之外,秒杀系统也越来越成为电商、抢购等平台的核心功能之一。本…...

音视频入门基础:RTP专题(8)——使用Wireshark分析RTP
一、引言 通过Wireshark可以抓取RTP数据包,该软件可以从Wireshark Go Deep 下载。 二、通过Wireshark抓取RTP数据包 首先通过FFmpeg将一个媒体文件转推RTP,生成RTP流: ffmpeg -re -stream_loop -1 -i input.mp4 -vcodec copy -an -f rtp …...

OpenAI 实战进阶教程 - 第六节: OpenAI 与爬虫集成实现任务自动化
爬虫与 OpenAI 模型结合,不仅能高效地抓取并分析海量数据,还能通过 NLP 技术生成洞察、摘要,极大提高业务效率。以下是一些实际工作中具有较高价值的应用案例: 1. 电商价格监控与智能分析 应用场景: 电商企业需要监控…...

SpringUI Web高端动态交互元件库
Axure Web高端动态交互元件库是一个专为Web设计与开发领域设计的高质量资源集合,旨在加速原型设计和开发流程。以下是关于这个元件库的详细介绍: 一、概述 Axure Web高端动态交互元件库是一个集成了多种预制、高质量交互组件的工具集合。这些组件经过精…...

解密企业安全密码:密钥管理服务如何重塑数据保护?
在数字化时代,数据是企业最宝贵的资产之一。然而,随着网络威胁的不断升级和数据泄露事件的频繁发生,如何保护企业数据的安全已成为每个组织面临的紧迫问题。传统的安全措施往往无法应对复杂的威胁环境,密钥管理服务作为企业信息安…...

基于keepalived+GTID半同步主从复制的高可用MySQL集群
文章目录 项目架构图项目名称项目环境项目描述ip地址规划项目步骤一.安装好8台全新的centos7.9的系统,关闭firewalld和selinux,配置每台主机的静态ip地址,设置每台主机对应的主机名。1、关闭firewalld2.关闭seLinux3.配置每台主机静态ip地址4…...

图片PDF区域信息批量提取至Excel,基于QT和阿里云api的实现方案
办公文档处理:在企业日常办公中,经常会遇到大量的扫描文档(如发票、合同、报表等)以图片或 PDF 格式存储。需要将这些文档中的特定区域信息(如发票金额、合同条款、报表数据等)提取出来,整理到 …...

Java 大视界 -- Java 大数据在智能教育中的应用与个性化学习(75)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也期待你毫无保留地分享独特见解,愿我们于此携手成长,共赴新程!💖 一、…...

从零手写Spring IoC容器(二):bean的定义与注册
从零手写Spring IoC容器(二):bean的定义与注册 一. 回顾简单容器的不足之处 在第一章中,我们实现了一个最简单的 IoC 容器,但该版本存在诸多不足,例如: Bean 的管理方式过于简单,…...

《大模型面试宝典》(2025版) 发布了
基于去年我们写的《大模型面试宝典》(2024版)的基础上,我根据自己实践经验和星球小伙伴的面经分享总结推出《大模型面试宝典》(2025版),共计52w字。 与去年相比,内容增加了星球成员面试真题分享、大模型最新考试要点总结、DeepSeek 项目实战…...

AWS门店人流量数据分析项目的设计与实现
这是一个AWS的数据分析项目,关于快消公司门店手机各个门店进店人流量和各个产品柜台前逗留时间(利用IoT设备采集)和销售数据之间的统计分析,必须用到但不限于Amazon Kensis Data Stream,Spark Streaming,Sp…...

出租车特殊计费表算法解析与实现
目录 引言算法核心概念 特殊计费规则解析数据类型与输入输出算法数学原理 数字位判断与处理逻辑数值转换与累加计算算法框架图Python 实现 代码展示代码解析Python 实现的优势与局限C 语言实现 代码展示代码解析C 语言实现的性能特点性能分析与优化 性能分析 时间复杂度空间复杂…...

文档解析技术:如何高效提取PDF扫描件中的文字与表格信息?
想要高效提取PDF扫描件中的文字与表格信息,通常需要借助专业的工具或在线服务,以下是一些可行的方法: 预处理扫描件:在提取文字之前,尽量确保扫描件的图像质量清晰。如果扫描件模糊或有污渍,可以使用图像处…...

【2】高并发导出场景下,服务器性能瓶颈优化方案-异步导出
Java 异步导出是一种在处理大量数据或复杂任务时优化性能和用户体验的重要技术。 1. 异步导出的优势 异步导出是指将导出操作从主线程中分离出来,通过后台线程或异步任务完成数据处理和文件生成。这种方式可以显著减少用户等待时间,避免系统阻塞&#x…...

【DeepSeek论文精读】6. DeepSeek R1:通过强化学习激发大语言模型的推理能力
欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html)原创作品 【DeepSeek论文精读】1. 从 DeepSeek LLM 到 DeepSeek R1 【DeepSeek论文精读】6. DeepSeek R1:通过强化学习激发大语言模型的推理能力 【DeepSeek论…...

frida 通过 loadLibrary0 跟踪 System.loadLibrary
static {System.loadLibrary("libxxx.so"); }在 ndk 开发中,常见的实践是在 static 代码块里调用 loadLibrary 加载动态库。由于 apk 从 java 层开始启动,过早地 hook 原生代码会找不到函数。所以一种常见做法是在 loadLibrary 的 hook 回调里…...

【2025最新计算机毕业设计】基于SSM的智能停车场管理系统【提供源码+答辩PPT+文档+项目部署】(高质量源码,可定制,提供文档,免费部署到本地)
作者简介:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容:🌟Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…...

【含文档+PPT+源码】Python爬虫人口老龄化大数据分析平台的设计与实现
项目介绍 本课程演示的是一款Python爬虫人口老龄化大数据分析平台的设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Python学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本…...

文本生图的提示词prompt和参数如何设置(基于Animagine XL V3.1)
昨天搞了半天 Animagine XL V3.1,发现市面上很多教程只是授之以鱼,并没有授之以渔的。也是,拿来赚钱不好吗,闲鱼上部署一个 Deepseek 都能要两百块。这里我还是想写篇文章介绍一下,虽不全面,但是尽量告诉你…...

快速提取Excel工作簿中所有工作表的名称?
大家好,我是小鱼。 在Excel表格中如何快速提取工作簿中所有工作表的名称?这个问题在日常工作中也经常遇到,比如说经常使用的INDIRECT函数跨工作表汇总或者制作类似于导航的工作表快捷跳转列表,就需要每个工作表的名称。如果工作表…...

【紫光同创PG2L100H开发板】盘古676系列,盘古100Pro+开发板,MES2L676-100HP
本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com) 一:开发系统介绍 开发系统概述 MES2L676-100HP开发板采用紫光创 logos2系列 FPGA,型号&#x…...

Node.JS 版本管理工具 Fnm 安装及配置(Windows)
Fnm 安装及配置(Windows) Fnm(Fast Node Manager)?? 一个快速而简单的 Node.js 版本管理工具,使用 Rust 编写。 1 安装 官网:Fnm(镜像网站 )。 下载:Fnm(…...

labview通过时间计数器来设定采集频率
在刚接触labview的时候,笔者通常用定时里的等待函数来实现指令的收发,但是当用到的收发消息比较多时就出现了卡顿,卡死的情况,这是因为当用队列框架时,程序卡在了其中的一个分支里,等通过相应的延时后才可以…...

汇编JCC条件跳转指令记忆
汇编中的条件跳转指令(JCC): 1. 理解标志寄存器 JCC 指令依赖于标志寄存器(FLAGS)的状态,常见的标志位有: ZF(Zero Flag):结果为0时置1。 CF(Ca…...