SpringAOP详解(二)

SpringAOP详解(二)

一、代理模式的核心概念

1. 定义

为目标对象提供 “代理类”,让调用方不直接访问目标对象,而是通过代理类间接访问,从而在代理类中实现功能增强(比如日志、权限校验)。

2. 核心角色(以 “房屋租赁” 为例)
角色对应示例作用说明
SubjectHouseSubject接口定义目标对象和代理类的共同行为(比如 “租房”)
RealSubjectRealHouseSubject(房东)目标对象(被代理的实际业务执行者)
ProxyHouseProxy(中介)代理类,包装目标对象,在调用目标方法前后添加增强逻辑

静态代理的实现步骤(以房屋租赁为例)

1. 定义共同接口(Subject)
2. 实现目标对象(RealSubject)
3. 实现代理类(Proxy)
4. 使用代理
静态代理的核心特点
  • 提前创建:代理类的.class文件在程序运行前就已存在(比如HouseProxy是提前写好的);
  • 功能增强:不修改目标对象代码,通过代理类实现 “附加逻辑”(符合 “开闭原则”);
  • 局限性:一个代理类只能代理一种类型的目标对象,若要代理多个类,需写多个代理类(所以 Spring AOP 实际用的是动态代理,解决这个局限性)。
和 Spring AOP 的关系

静态代理是代理模式的基础,而 Spring AOP 的底层是动态代理(运行时自动生成代理类),但核心思想一致:通过代理类包装目标对象,实现无侵入的功能增强。

二、动态代理的核心优势

相比静态代理,动态代理无需为每个目标对象写单独的代理类,而是在程序运行时动态生成代理对象,更灵活、更通用。

2.1JDK 动态代理的实现步骤(以房屋租赁为例)
步骤 1:准备 “干活的对象”(目标对象)
  • 目标:确定 “要被代理的实体 + 要干的活”;
  • 人话:找个 “房东”(RealHouseSubject),他会干 “租房”(rentHouse 方法)这个活;
  • 代码对应
步骤 2:写 “中介的规则”(InvocationHandler)
  • 目标:定义 “中介要在房东干活前后加什么额外操作”;
  • 人话:中介(JDKInvocationHandler)要在房东租房前说 “开始代理”,租房后说 “代理结束”;
  • 代码对应
步骤 3:生成 “中介”(动态代理对象)
  • 目标:让 JVM 自动创建 “中介”,代替房东和用户打交道;
  • 人话:告诉 JVM“用房东的类加载器、房东会的活(接口)、中介的规则”,生成一个中介;
  • 代码对应
步骤 4:看结果(验证逻辑)

运行后输出:

3.JDK 动态代理的关键 API
API作用说明
InvocationHandler方法调用处理器接口,invoke方法是代理增强逻辑的入口(参数含代理对象、目标方法、方法参数)。
Proxy.newProxyInstance动态生成代理对象的核心方法,需传入类加载器、目标对象实现的接口、InvocationHandler 实例
4.JDK 动态代理的局限性

只能代理实现了接口的类(因为newProxyInstance需要传入接口数组)。若要代理无接口的类,需用CGLIB 动态代理(后续内容)。

5.和 Spring AOP 的关系

Spring AOP 默认优先用JDK 动态代理(代理有接口的类),若目标类无接口,则自动切换为CGLIB 动态代理,底层逻辑与上述一致 —— 通过动态生成代理类实现无侵入的功能增强。

三、AOP + 代理模式核心拆解

第一层:先搞懂“目标对象”
核心逻辑

目标对象 = Spring 管理的 Bean(比如 Controller/Service) + 这个 Bean 里的业务方法(比如接口方法 / 保存用户方法)

解释

就是 “真正干活的对象 + 具体要干的活”,比如:

  • 干活的对象:UserController实例(Spring 自动创建的 Bean);
  • 具体的活:getUserById(Long id)方法(查询用户的业务逻辑)。
第二层:为什么需要“代理”(AOP 的本质)
核心逻辑

不想修改目标对象的代码,但想给 “具体的活” 加额外逻辑(日志 / 权限 / 事务)→ 找个 “中间人”(代理对象)帮我们加。

解释

比如:房东(目标对象)只想 “租房”(核心活),不想管 “带看房 / 签合同”(额外活)→ 找中介(代理对象),中介帮房东加这些额外活,房东只干核心的租房。

第三层:「静态代理」vs「动态代理」(代理的两种方式)
类型核心逻辑人话解释
静态代理提前写死代理类(一个目标对象对应一个代理类)给房东 A 写个专属中介,给房东 B 写另一个专属中介
动态代理运行时自动生成代理类(所有目标对象共用一套逻辑)一个中介公司,能代理所有房东,不用单独写中介
关键:Spring AOP 用的是“动态代理”
  • JDK 动态代理:代理有接口的类(比如 Controller/Service 都实现了接口);
  • CGLIB 动态代理:代理没接口的类(兜底方案)。
第四层:Spring AOP 的核心组件(代理的 “包装”)

把动态代理的逻辑封装成 3 个好懂的组件,不用自己写代理类:

1. 切面类(@Aspect + @Component)
  • 核心逻辑:告诉 Spring “这是一个 AOP 增强类”,并交给 Spring 管理;
  • 人话:就是 “中介公司的规则手册”,定义了 “要帮哪些房东干活 + 要加哪些额外活”。
2. 切点(execution/@annotation)
  • 核心逻辑:划定 “要增强哪些目标对象的方法”(哪些房东要被代理);
  • 人话:规则 1:“只代理朝阳区的房东”(execution 匹配包 / 类);规则 2:“只代理贴了“急租”标签的房东”(@annotation 匹配注解)。
3. 通知(@Before/@Around 等)
  • 核心逻辑:定义 “要加的额外活”(什么时候加、加什么);
  • 人话:规则:“带客户看房(@Before)→ 房东租房 → 收中介费(@After)”。
第五层:完整执行流程

以 “访问 UserController 的 getUserById 方法” 为例:

  1. 你调用userController.getUserById(1) → 实际调用的是 Spring 生成的“代理对象”;
  2. 代理对象先执行通知逻辑(比如 @Before 打印日志);
  3. 代理对象调用“目标对象”的getUserById(1)(真正的查询逻辑);
  4. 代理对象再执行后续通知(比如 @After 统计耗时);
  5. 返回结果给你。
核心总结(一句话)

Spring AOP = 动态代理(自动生成中介) + 切面(中介规则) + 切点(选房东) + 通知(加额外活),最终实现 “不修改目标对象代码,却能增强其方法”。

四、CGLIB 动态代理

1.先搞懂:CGLIB 是干嘛的?

JDK 动态代理只能代理 “有接口的类”,而CGLIB 是用来代理 “没有接口的类”(比如普通的 Java 类),它的原理是动态生成目标类的子类,通过子类来实现增强。

2.CGLIB 动态代理的 3 步核心动作
步骤 1:准备 “要被代理的类”(不用接口!)
  • 目标:找一个 “没实现接口的类”(比如普通的房东类);
  • 人话:房东类RealHouseSubject没实现任何接口,但会干 “租房” 这个活;
  • 代码对应
步骤 2:写 “增强规则”(MethodInterceptor)
  • 目标:定义 “代理要在房东干活前后加什么操作”;
  • 人话:中介(CGLIBInterceptor)要在房东租房前说 “开始代理”,租房后说 “代理结束”;
  • 代码对应
步骤 3:生成 “代理子类”(Enhancer.create)
  • 目标:让 CGLIB 动态生成目标类的子类(代理类);
  • 人话:告诉 CGLIB“要代理的类 + 增强规则”,生成一个 “房东的子类(中介)”;
  • 代码对应
步骤 4:看结果(和 JDK 代理一样)

运行后输出:

3.CGLIB 和 JDK 代理的核心对比
维度JDK 动态代理CGLIB 动态代理
代理条件必须实现接口可以代理无接口的类(生成子类)
核心 APIInvocationHandler + ProxyMethodInterceptor + Enhancer
底层原理基于接口的动态代理基于子类的动态代理
Spring AOP 场景优先用(代理有接口的 Bean)兜底用(代理无接口的 Bean)
4.总结 CGLIB

CGLIB 是 JDK 代理的 “补位方案”—— 专门解决 “无接口类的代理问题”,通过生成目标类的子类,实现和 JDK 代理一样的增强效果,Spring AOP 会自动在 JDK 和 CGLIB 之间切换。

五、Spring AOP 的源码

1.Spring AOP 的核心逻辑:谁来生成代理?

Spring AOP 生成代理的核心类是AnnotationAwareAspectJAutoProxyCreator,它的父类AbstractAutoProxyCreator里的createProxy方法,是生成代理的 “入口”。

2.生成代理的 3 步核心流程(源码逻辑)
步骤 1:创建 “代理工厂”(ProxyFactory)
  • 目标:封装代理的配置信息(比如用 JDK 还是 CGLIB);
  • 代码对应
步骤 2:决定 “用 JDK 还是 CGLIB”(核心判断)

通过proxyTargetClass这个配置项,决定代理方式:

proxyTargetClass 值目标对象情况代理方式
false(默认)实现了接口JDK 代理
false(默认)没实现接口CGLIB 代理
true不管有没有接口CGLIB 代理
步骤 3:生成代理对象(调用 JDK/CGLIB 的 API)

代理工厂通过getProxy方法,最终调用我们之前学的 JDK/CGLIB API 生成代理:

  • JDK 代理:调用Proxy.newProxyInstance(对应JdkDynamicAopProxy类);
  • CGLIB 代理:调用Enhancer.create(对应CglibAopProxy类);

3.Spring Boot 中的关键配置

  • Spring Boot 2.x 开始,默认用 CGLIB 代理(相当于默认proxyTargetClass=true);
  • 若要改回 JDK 代理,需在配置文件加:
4.一句话总结 Spring AOP 源码逻辑

Spring AOP 通过ProxyFactory封装配置,根据proxyTargetClass和 “目标类是否有接口”,自动选择 JDK/CGLIB 代理,最终调用对应的动态代理 API 生成代理对象 ——我们之前学的 JDK/CGLIB,就是 Spring AOP 的底层实现

你只写核心业务代码,想加额外功能时,不用改业务代码,只需要写 AOP 的切面 / 切点规则就行

六、拆解aop思想

  • 切面表达式(@Pointcut)只是选目标(选哪些业务 / 接口要加功能);
  • 真正的 “额外功能代码”(比如打日志、校验权限)要写在@Before/@After/@Around这些「通知」里;
  • 整体逻辑是:写切面类 → 用切点选目标 → 用通知写额外功能,全程不用碰你的核心业务代码。

2.分清:拦截器、统一异常、AOP 各自管啥

把你的后端系统想象成一个「餐厅」:

组件角色定位管的范围核心作用例子(对应你的接口开发)
拦截器餐厅门口的保安只管「接口请求的进出」拦截HTTP请求(进)/响应(出),管请求级的事校验token、限制接口访问频率、记录请求URL
统一异常餐厅的售后客服只管「全局异常兜底」捕获所有未处理的异常,统一返回格式接口抛空指针/数据库异常时,返回统一的{code:500,msg:“失败”}
AOP餐厅里的「万能服务员」管「任意方法的任意时机」任意方法(接口/Service/工具类)加功能给Service层加事务、给指定方法打详细日志、统计方法执行耗时

3.关键:啥时候用 AOP?(对比拦截器 / 统一异常)

核心判断标准:当你要给「非接口级的方法」加额外功能,或者需要更细粒度的控制时,就用 AOP

场景 1:拦截器管不到的地方,必须用 AOP

拦截器只能拦「Controller 层的 HTTP 请求」,但你后端的核心逻辑在 Service 层、Mapper 层,这些地方想加额外功能,只能用 AOP:

  • 例子 1:想统计「用户下单 Service 方法」的执行耗时 → 拦截器拦不到 Service 方法,用 AOP 的@Around包一下这个 Service 方法就行;
  • 例子 2:想给「所有修改数据的 Mapper 方法」加日志(记录谁改了、改了啥)→ Mapper 层没有 HTTP 请求,拦截器没用,AOP 可以精准切这些 Mapper 方法。
场景 2:需要更细粒度的控制,用 AOP

拦截器是 “要么拦整个接口,要么不拦”,但 AOP 可以精准到「某个类的某个方法」「带某个注解的方法」:

  • 例子 1:同一个 Controller 里,只想给「删除用户」方法加权限校验,其他方法不加 → 拦截器做不到(拦就全拦),AOP 的切点可以只切这个删除方法;
  • 例子 2:想给「所有带 @Transactional 注解的方法」加事务执行日志 → 用 AOP 切带这个注解的方法就行,拦截器做不到。
场景 3:拦截器 / AOP 都能做,但 AOP 更合适的情况

比如 “接口打日志”:

  • 拦截器能打(记录请求 URL、参数),但只能拿到 HTTP 层面的信息;
  • AOP 能打更细的日志(比如拿到 Service 层的入参、出参、方法名),还能区分 “接口成功 / 失败” 的日志格式,更灵活。
场景 4:统一异常和 AOP 的配合

统一异常是「兜底捕获所有异常」,但 AOP 可以「在异常发生时做额外处理」:

  • 比如:接口抛异常后,除了统一返回错误信息,还想记录 “异常方法名、参数、堆栈信息到专门的日志文件” → 用 AOP 的@AfterThrowing(异常通知)来做,统一异常只负责返回格式,AOP 负责记录详细异常日志。

4.作为后端,记这 3 个 “使用原则” 就够了

  1. 管接口请求 / 响应 → 用拦截器:比如 token 校验、跨域、接口限流;
  2. 管全局异常格式 → 用统一异常处理器:比如@RestControllerAdvice + @ExceptionHandler
  3. 管方法级的额外功能 → 用 AOP:比如 Service 层加日志 / 事务 / 耗时统计、精准切某个方法加权限 / 校验。

总结

  1. 核心:AOP 是「方法级」的增强,拦截器是「接口请求级」的增强,统一异常是「全局异常兜底」,三者分工不同、可以配合使用;
  2. 什么时候用 AOP:拦截器管不到(比如 Service/Mapper 层)、需要细粒度控制(比如只切某个方法)时,就用 AOP;
  3. 你的工作方式:核心业务代码不动,加额外功能时,接口级的用拦截器,方法级的用 AOP(写切面 + 切点 + 通知),异常兜底用统一异常。

Read more

逛逛的粉丝推荐的 GitHub 项目,收藏一波。

01 论文配图自动生成:AutoFigure-Edit 写论文最头疼的是什么?画图啊!尤其是那些流程图、架构图,画一张得折腾半天。 最近在 GitHub 上发现一个叫 AutoFigure-Edit 的开源项目,专门解决这个问题。它入选了 ICLR 2026,属于学术圈的正经工具。 说白了,这玩意儿就是把你的论文方法部分文字丢进去,它能自动生成专业的论文配图,而且是可编辑的 SVG 格式。 它的核心工作流程是这样的:先用 LLM 根据文字生成一个草图,然后用 SAM3 做图像分割识别出各个图标区域,再通过 RMBG-2.0 去背景,最后组装成完整的矢量图。 最牛的是它支持风格迁移,你可以丢一张参考图进去,它会模仿那个风格来画你的图。这对于想要统一论文配图风格的人来说,简直是救星。 项目还内置了一个 Web 界面,生成的图可以直接在浏览器里编辑,拖拖拽拽就能调整,非常方便。 开源地址:https://github.

By Ne0inhk
GitHub免费开源!World Monitor:开源全球情报仪表盘

GitHub免费开源!World Monitor:开源全球情报仪表盘

一、项目定位:AI驱动的全域态势感知平台 在全球化浪潮与地缘政治格局加速演变的当下,分散的新闻资讯、碎片化的地缘数据、割裂的基础设施监控渠道,让全球局势的洞察者面临“信息过载却又不全”的困境。由开发者cn620主导的开源项目World Monitor,正是为解决这一痛点而生——它是一款基于AI驱动的实时全球情报仪表盘,通过统一的态势感知界面,整合新闻聚合、地缘政治监控、基础设施跟踪三大核心能力,为用户提供一站式、高精度的全球局势洞察工具。 开源地址获取:World Monitor:https://www.gegeblog.top/article/87 二、核心功能模块:三重维度的全球情报覆盖 (一)AI驱动的智能新闻聚合 不同于传统新闻客户端的“被动推送”,World Monitor的新闻聚合能力核心在于AI的深度介入: 1. 多源实时采集:项目通过AI爬虫框架同步抓取全球百余家权威新闻源,包括路透社、美联社、BBC等国际媒体,以及各国官方机构公报、专业地缘政治数据库(如CSIS全球冲突数据库),覆盖英文、中文、阿拉伯文等多语种内容;

By Ne0inhk
1.5k stars!阿里开源 PageAgent:让 AI 直接“住进“你的网页,用自然语言操控一切!

1.5k stars!阿里开源 PageAgent:让 AI 直接“住进“你的网页,用自然语言操控一切!

阿里开源 PageAgent:让 AI 直接"住进"你的网页,用自然语言操控一切 不需要浏览器插件,不需要 Python,不需要截图——一行 JS,让你的网页秒变 AI 智能体。 一、先说痛点:Web 自动化为什么这么难? 如果你用过 Selenium、Playwright,或者最近流行的 browser-use,你一定遇到过这些头疼的问题: * 环境太重:得装 Python、headless 浏览器、各种依赖,部署复杂,维护成本高; * 依赖截图 + OCR:很多方案靠多模态模型"看图操作",慢、贵、还不准; * 权限门槛高:要控制浏览器,往往需要特殊权限甚至操作系统级别的访问; * 对现有产品改造成本大:

By Ne0inhk
WebGIS + 无人机 + AI:下一代智能巡检系统?

WebGIS + 无人机 + AI:下一代智能巡检系统?

WebGIS 遇上无人机,再叠加 AI 能力,巡检不再只是“看画面”,而是变成“智能决策系统”。 一、为什么 WebGIS + 无人机 + AI 是趋势? 在传统巡检场景中: * 电力巡检 → 人工拍照 * 工地巡查 → 人工记录 * 农业监测 → 靠经验判断 * 安防巡逻 → 事后回放 问题: * 数据无法实时分析 * 缺乏空间关联 * 没有智能预警能力 * 无法形成可视化决策系统 而结合: * WebGIS(三维可视化) * 无人机(数据采集) * AI(智能识别与分析) 我们可以构建: 一个真正的“空天地一体化智能巡检系统” 二、整体技术架构设计 1、系统分层架构 ┌──────────────────────────────┐ │ 前端可视化层 │ │ Cesium + Three.js + WebGL │ └──────────────┬───────────────┘ │ ┌──────────────▼───────────────┐ │ 业务中台层 │ │ AI推理

By Ne0inhk