Spring AI 学习指南(六)Advisor高阶机制实战
统一环境:IDEA2026.1.1、JDK21、SpringBoot3.5.14、SpringAI1.1.6、智谱glm-4-flash、MySQL8.0
前置阅读:已掌握 Spring AI 分层记忆架构、JDBC 数据库持久化记忆、ChatClient 链式调用基础
一、前言
在前几期记忆实战中,我们借助官方提供的 MessageChatMemoryAdvisor,快速实现了 AI 多轮对话的上下文记忆与数据库持久化能力,解决了 AI 对话无状态、会话数据丢失的问题。
但在实际生产开发中,仅靠官方自带的记忆顾问远远不够,我们往往需要实现全局日志审计、自定义请求拦截、业务参数透传、会话权限校验等通用扩展能力。而支撑这些高阶功能的核心底层,正是 Spring AI 框架的核心扩展机制 —— Advisor 顾问机制。
多数初学者在使用 Advisor 时,普遍存在两大痛点:
-
不理解多 Advisor 共存时的 Order 优先级执行规则,经常出现功能失效、执行顺序错乱等问题
-
不熟悉 param 上下文参数透传机制,无法实现跨顾问参数共享,难以拓展自定义业务能力
本篇将基于 SpringAI1.1.6 标准 BaseAdvisor 接口,以可动态配置的日志顾问为实战案例,结合 Spring 拦截器设计思想,讲透 Advisor 核心原理与落地用法。
二、Advisor 核心定位:类比 Spring MVC 拦截器
2.1 核心设计思想
Spring AI 的 Advisor 顾问机制,设计思路与 Spring MVC 拦截器(HandlerInterceptor) 高度一致,是框架提供的全局 AOP 扩展入口,核心作用是在不侵入业务代码的前提下,对 AI 对话全链路进行统一增强。
-
Spring MVC 拦截器:在 Controller 接口执行前后,完成权限校验、日志记录、参数预处理
-
Spring AI Advisor:在 大模型 LLM 调用前后,完成上下文处理、请求拦截、日志审计、参数透传
核心设计理念:业务与通用增强解耦,全局统一生效,灵活拓展 AI 对话能力。
2.2 BaseAdvisor 标准执行流程
BaseAdvisor 是 Spring AI 官方标准顶层顾问接口,定义了 AI 对话全生命周期的拦截方法,核心包含两个核心阶段:
-
before() 前置执行:大模型调用前触发,可实现参数修改、请求拦截、上下文参数绑定等操作
-
after() 后置执行:大模型调用结束后触发,可实现响应结果处理、对话日志记录、数据持久化等操作
完整对话执行链路:客户端请求 → 多Advisor链式执行before前置逻辑 → LLM大模型调用 → 多Advisor链式执行after后置逻辑 → 响应结果返回客户端
三、Order 优先级核心机制(重点)
当项目中存在多个自定义顾问、官方顾问共存时,执行顺序完全由 getOrder() 返回值控制,这是解决多顾问冲突、功能失效的核心关键。
3.1 优先级通用规则
-
前置 before 方法:Order 值越小,优先级越高,越先执行
-
后置 after 方法:Order 值 越小,优先级越低,越晚执行(与前置执行顺序完全相反)
3.2 本篇实战优先级配置
本次实战同时启用「日志自定义顾问」和「官方记忆顾问」,采用生产级优先级配置:
-
LogAdvisor(Order=-100):高优先级,最先执行前置日志拦截,最后执行后置日志打印
-
MessageChatMemoryAdvisor(Order=0):默认优先级,负责对话记忆的加载与存储
最终完整执行链路:日志前置打印 → 加载历史对话记忆 → 调用大模型 → 保存本轮对话记忆 → 日志后置打印
3.3 动态 Order 配置优势
本次自定义日志顾问采用 Builder 构建器模式,支持动态传入 Order 优先级,摒弃硬编码方式。开发者可在配置类中灵活调整顾问执行顺序,适配不同业务场景,扩展性与灵活性更强。
四、核心知识点:param 上下文参数透传
4.1 核心作用
Spring AI 提供 .param(key,value) 方法,支持向 Advisor 全局上下文透传自定义参数,实现跨业务、跨顾问的数据共享,是实现会话隔离、权限控制、日志追踪的核心基础:
-
透传会话 ID(conversationId),实现多用户、多会话对话隔离
-
透传 Token、用户 ID、设备信息等自定义业务参数
-
实现所有注册顾问全局共享参数,统一处理上下文数据
4.2 参数传递完整链路
Controller 接口通过 advisors().param() 绑定自定义参数 → 参数存入全局 AdvisorContext 上下文 → 所有 Advisor 的 before/after 方法可通过请求对象获取上下文参数 → 实现全局参数透传与复用。
五、实战一:自定义可配置日志顾问 LogAdvisor
基于标准 BaseAdvisor 接口,结合 Builder 模式实现可动态配置优先级的全局日志顾问,自动打印 AI 对话请求、响应及上下文参数,实现全链路日志审计。
package demo.ai.advisor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.api.*;
import org.springframework.stereotype.Component;
/**
* 全局日志记录顾问
* 基于 BaseAdvisor 标准接口开发
* 支持Builder动态配置Order优先级,打印完整AI对话请求、响应与上下文参数
*/
@Slf4j
@Component
public class LogAdvisor implements BaseAdvisor {
private int order;
@Override
public String getName() {
return "Log Advisor";
}
/**
* 模型调用前置执行
* 打印请求信息、上下文透传参数
*/
@Override
public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {
log.info("beforeLog: {}", chatClientRequest);
log.info("beforeLog context: {}", chatClientRequest.context());
return chatClientRequest;
}
/**
* 模型调用后置执行
* 打印响应结果、上下文参数
*/
@Override
public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {
log.info("afterLog: {}", chatClientResponse);
log.info("afterLog context: {}", chatClientResponse.context());
return chatClientResponse;
}
@Override
public int getOrder() {
return order;
}
public static LogAdvisor.Builder builder() {
return new LogAdvisor.Builder();
}
public static final class Builder {
private int order = 0;
public LogAdvisor.Builder order(int order) {
this.order = order;
return this;
}
public LogAdvisor build() {
LogAdvisor logAdvisor = new LogAdvisor();
logAdvisor.order = this.order;
return logAdvisor;
}
}
}
六、实战二:全局配置整合记忆与日志顾问
沿用前文 JDBC 数据库持久化记忆配置,同时注册官方记忆顾问与自定义日志顾问,手动指定优先级,保证多顾问有序执行,实现对话持久化+全局日志审计双重能力。
package demo.ai.conf;
import demo.ai.advisor.LogAdvisor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.jdbc.MysqlChatMemoryRepositoryDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
@Configuration
public class ChatMemoryConfig {
/**
* 1. 升级为JDBC数据库持久化仓库(MySQL方言)
*/
@Bean
public JdbcChatMemoryRepository chatMemoryRepository(JdbcTemplate jdbcTemplate) {
// 指定MySQL方言,适配数据库语法
return JdbcChatMemoryRepository.builder()
.jdbcTemplate(jdbcTemplate)
.dialect(new MysqlChatMemoryRepositoryDialect())
.build();
}
/**
* 2. 滑动窗口记忆策略(完全复用,无需改动)
* 最大保留10条消息,自动裁剪过期消息
*/
@Bean
public MessageWindowChatMemory chatMemory(JdbcChatMemoryRepository repository) {
return MessageWindowChatMemory.builder()
.chatMemoryRepository(repository)
.maxMessages(10)
.build();
}
/**
* 3. 构建全局ChatClient,批量注册顾问并指定优先级
* LogAdvisor:Order=-100,优先级最高,优先完成日志拦截
* MessageChatMemoryAdvisor:Order=0,默认优先级,处理对话记忆读写
*/
@Bean
public ChatClient chatClient(ChatClient.Builder builder, MessageWindowChatMemory chatMemory) {
return builder
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).order(0).build(), LogAdvisor.builder().order(-100).build())
.build();
}
}
七、实战三:Controller 上下文参数透传
在接口层通过 param 透传会话 ID、自定义 Token 参数,实现多会话隔离与全局参数共享,所有参数可在 Advisor 拦截逻辑中获取并使用。
package demo.ai.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/memory")
public class ChatMemoryController {
@Resource
private ChatClient chatClient;
@Resource
private ChatMemory chatMemory;
/**
* 带记忆的普通多轮对话
* 透传会话ID实现多用户隔离,自定义Token实现业务参数追踪
*/
@GetMapping("/chat")
public String memoryChat(@RequestParam String sessionId,
@RequestParam String msg) {
return chatClient.prompt()
// 传入会话ID,隔离不同用户对话
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, sessionId).param("token", "token123"))
.system("你是专业的医院挂号咨询助手,回答简洁、易懂、专业")
.user(msg)
.call()
.content();
}
/**
* 带记忆的流式多轮对话
* 透传会话ID实现多用户隔离,自定义Token实现业务参数追踪
*/
@GetMapping("/stream")
public Flux<String> memoryStreamChat(@RequestParam String sessionId,
@RequestParam String msg) {
return chatClient.prompt()
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, sessionId).param("token", "token123"))
.system("你是专业的医院挂号咨询助手,分段清晰、简洁回答问题")
.user(msg)
.stream()
.content();
}
/**
* 清空指定会话记忆
*/
@GetMapping("/clear")
public String clearMemory(@RequestParam String sessionId) {
chatMemory.clear(sessionId);
return "会话【" + sessionId + "】记忆已清空";
}
}
pom.xml、application.yml参照上一次教程。
八、核心原理深度复盘
8.1 上下文Param传递原理
通过advisor.param(k,v) 绑定的自定义参数,会统一存入框架内置的 AdvisorContext 全局上下文,贯穿整个 AI 调用链路。所有已注册的 Advisor 均可读取上下文参数,完美实现业务参数与框架增强逻辑解耦,常用于会话隔离、权限校验、日志追踪、用户信息透传等场景。
8.2 多Advisor完整执行链路复盘
结合本次优先级配置,完整执行顺序清晰可控,无冲突、无逻辑遗漏:
-
LogAdvisor 前置方法执行(Order=-100):打印请求信息与上下文参数
-
MessageChatMemoryAdvisor 前置方法执行:从 MySQL 加载对应会话的历史对话记忆
-
框架调用大模型 LLM,生成 AI 响应结果
-
MessageChatMemoryAdvisor 后置方法执行:保存本轮对话数据至数据库,自动裁剪消息窗口
-
LogAdvisor 后置方法执行:打印响应结果与最终上下文参数
九、功能测试验证
9.1 全局日志打印测试
调用接口 http://localhost:8080/memory/chat?sessionId=user001&msg=咨询内科挂号时间,控制台可正常打印完整请求信息、sessionId、自定义 token 及 AI 响应结果,全链路日志完整,参数透传生效。
9.2 JDBC记忆持久化测试
多轮对话数据可正常存入 MySQL 数据表,重启服务后历史记忆不丢失,记忆顾问与日志顾问完美共存,功能互不冲突。
9.3 上下文参数透传测试
自定义 Token、会话 ID 可成功透传至 Advisor 上下文,开发者可基于该能力拓展权限校验、会话拦截、日志追踪等自定义功能。
十、踩坑总结
-
Order优先级错乱:多顾问共存场景必须手动指定 Order 值,默认 0 会导致执行顺序不可控,出现日志缺失、记忆加载异常等问题
-
接口使用不规范:项目统一使用标准 BaseAdvisor 接口开发,保证代码规范、版本适配统一,避免框架兼容问题
-
上下文参数获取为空:自定义参数必须在
advisors()方法中绑定,直接在 prompt 中设置无法透传到 Advisor 上下文 -
硬编码优先级扩展性差:推荐使用 Builder 模式动态配置 Order,灵活适配不同业务场景,便于后期维护迭代
十一、本篇学习总结
本篇聚焦 Spring AI 核心扩展能力,彻底吃透 Advisor 高阶机制,核心收获总结如下:
-
明确 Advisor 核心定位:AI 对话场景的全局拦截扩展机制,与 Spring MVC 拦截器设计思想一致
-
熟练掌握 Order 优先级执行规则,可自主管控多顾问执行顺序,解决共存冲突问题
-
吃透 param 上下文参数透传机制,实现跨顾问全局参数共享
-
掌握 BaseAdvisor 标准开发方式,实现可配置、可拓展的自定义顾问
-
整合 JDBC 持久化记忆与日志拦截能力,搭建解耦、稳定的企业级 AI 对话架构
十二、结语
Advisor 是 Spring AI 框架的核心扩展基石,日志审计、权限拦截、限流监控、RAG 增强、AI Agent 等所有高阶能力,均基于该机制实现。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)