别再每次调用 AI 都写重复的鉴权、日志、敏感词检测代码了------Spring AI Advisor 给你一条可复现的路,把横切逻辑像乐高一样拆装。
先附上一张Spring AI Advisor架构图

先给结论
Spring AI Advisor 是一个可插拔的请求/响应增强机制,通过责任链模式组合多个横切关注点,让 AI 应用的横切逻辑管理变得简单优雅。
为什么需要 Advisor
没有 Advisor 时,每次调用都要写一堆重复代码:
java
public String callAI(String input) {
if (!authService.check(input)) return "无权限";
if (containsSensitiveWords(input)) return "敏感内容";
List<ChatMessage> history = memoryService.getHistory();
ChatResponse response = model.call(new Prompt(input, history));
logger.info("调用AI:输入={},输出={}", input, response);
memoryService.save(input, response);
if (checkOutput(response)) return "输出有风险";
return response.getContent();
}
有 Advisor 后,业务代码回归干净:
java
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(
new AuthAdvisor(),
new SensitiveWordAdvisor(),
new MessageChatMemoryAdvisor(chatMemory),
new MyLoggerAdvisor()
)
.build();
String answer = chatClient.prompt().user("你好").call().content();
Advisor 的核心原理
1. 责任链模式
- 前置处理:按 Order 值升序执行(值小先执行)
- 后置处理:按 Order 值降序执行(后进先出)
- 短路机制:某个 Advisor 可以直接返回,不继续调用模型
2. 短路能力
java
public class SensitiveWordAdvisor implements CallAroundAdvisor {
@Override
public AdvisedResponse aroundCall(AdvisedRequest req, CallAroundAdvisorChain chain) {
for (String word : blockedWords) {
if (req.userText().contains(word)) {
AssistantMessage rejection = new AssistantMessage("抱歉,内容不合规,无法回答。");
ChatResponse chatResponse = new ChatResponse(List.of(new Generation(rejection)));
return AdvisedResponse.from(chatResponse).advisorContext(req.advisorContext()).build();
}
}
return chain.nextAroundCall(req);
}
}
3. 自定义 Advisor 四步
- 同时实现
CallAroundAdvisor+StreamAroundAdvisor - 重写
aroundCall/aroundStream - 设置
getOrder() - 返回唯一
getName()
实战案例:RAG + Advisor
java
@Service
public class KnowledgeService {
private final ChatClient chatClient;
public KnowledgeService(ChatClient.Builder builder, VectorStore vectorStore) {
this.chatClient = builder
.defaultSystem("请基于提供的上下文信息回答问题,上下文不足就明确说明,不要编造。")
.defaultAdvisors(
new QuestionAnswerAdvisor(vectorStore),
new AuthAdvisor(),
new MyLoggerAdvisor()
)
.build();
}
public String ask(String question) {
return chatClient.prompt().user(question).call().content();
}
}
踩坑清单
Order 排序
java
new MyLoggerAdvisor(), // Order=0,最外层
new SecurityAdvisor(), // Order=10,安全检查
new RagAdvisor(vectorStore), // Order=50,RAG 检索增强
new MemoryAdvisor(chatMemory) // Order=100,最靠近模型
流式处理
java
// 错误:对每个 token 触发
chain.nextAroundStream(request).doOnNext(this::afterProcess)
// 正确:聚合完整响应
new MessageAggregator().aggregateAdvisedResponse(
chain.nextAroundStream(request), this::logAfter)
避免耗时操作
Advisor 同步执行,别在链里做外部 API 调用或复杂计算。
不适用的情况
- 需要异步处理时,Advisor 是同步的
- 复杂并行场景,责任链是串行的
- 性能敏感场景,多个 Advisor 会增加调用开销