Spring Boot 自动配置
这一页讲的是 starter 的真实装配链,而不是泛泛地说“它会自动配置一些 Bean”。
1. 真实入口类
核心入口是:
AiConfigAutoConfiguration
它做的事情不是单点注入,而是一整条装配链:
@EnableConfigurationProperties(...)绑定一组ai.*属性类@PostConstruct初始化统一Configuration- 创建
AiService - 创建
AiServiceFactory - 创建
AiServiceRegistry - 创建
FreeAiService - 条件性创建
VectorStore、RagContextAssembler、Reranker
2. 初始化顺序
AiConfigAutoConfiguration 里最关键的是 init():
- 初始化
OkHttpClient - 初始化各类向量数据库配置
- 初始化
SearXNG配置 - 初始化各 provider 配置
- 把这些对象写回统一
Configuration
这意味着你在 Spring Boot 下拿到的不是一堆互不相关的配置 Bean,而是已经被组织好的运行时图。
3. initOkHttp() 的意义
initOkHttp() 不是普通工具方法,它决定了整个 starter 的底层网络栈。
它会:
- 构造
HttpLoggingInterceptor - 通过
ServiceLoaderUtil.load(...)加载DispatcherProvider - 通过
ServiceLoaderUtil.load(...)加载ConnectionPoolProvider - 组装统一
OkHttpClient.Builder - 按配置加入代理和 SSL 策略
- 最后写回
Configuration.okHttpClient
这一步一旦失败,后面的 provider、vector、RAG、websearch 相关能力都会一起受影响,因为它们共享同一个底层客户端入口。
4. 单实例和多实例在这里怎么分流
单实例
如果你只配置一个 provider,主线通常是:
AiService
多实例
如果你配置了 ai.platforms[],主线通常是:
AiServiceRegistryAiServiceRegistrationFreeAiService
这不是同一个东西的不同名字,而是两条不同组织方式。
5. 条件装配的边界
starter 里并不是所有东西都无条件创建。
有些 Bean 是:
@ConditionalOnMissingBean@ConditionalOnProperty@ConditionalOnBean
这意味着默认 Bean 的存在是“可被接管”的,而不是强制覆盖业务实现。
5.1 向量库 Bean 全部是 opt-in
每个外部向量库都挂在自己的 ai.vector.<backend>.enabled=true 开关后面,不配就不进容器:
ai:
vector:
elasticsearch:
enabled: true
host: http://localhost:9200
index-name: kb_vectors
vector-dim: 1024
api-key: ${ES_API_KEY} # 或 username/password 走 Basic
chroma:
enabled: true
host: http://localhost:8000
collection: kb_docs
| 前缀 | Bean | 绑定属性类 |
|---|---|---|
ai.vector.pinecone | pineconeService + pineconeVectorStore | PineconeConfigProperties |
ai.vector.qdrant | qdrantVectorStore | QdrantConfigProperties |
ai.vector.milvus | milvusVectorStore | MilvusConfigProperties |
ai.vector.pgvector | pgVectorStore | PgVectorConfigProperties |
ai.vector.redis | redisVectorStore | RedisVectorConfigProperties |
ai.vector.elasticsearch | elasticsearchVectorStore | ElasticsearchConfigProperties |
ai.vector.chroma | chromaVectorStore | ChromaConfigProperties |
历史上 pineconeService / pineconeVectorStore 是无条件创建的——任何引入 starter 的应用容器里都会有这两个 Bean,导致多 VectorStore 并存时接口注入歧义。现在它们与其他后端一致:ai.vector.pinecone.enabled 未显式设 true 时不再创建。依赖旧行为的应用升级后需补上 enabled: true。
5.2 VectorStore 接口注入与 ai.vector.primary
starter 额外提供一个 @Primary 的 vectorStore Bean,让 @Autowired VectorStore 永远可注入:
- 只启用一个后端:自动选中它;
- 启用多个后端:必须用
ai.vector.primary指定默认后端,取值是后端名(qdrant/chroma/pinecone/milvus/pgvector/redis/elasticsearch)或自定义 VectorStore 的 Bean 名;未指定则启动直接失败并列出候选; - 要特定后端:注入具体类型(如
QdrantVectorStore)或按 Bean 名注入,不受影响。
ai:
vector:
primary: qdrant # 多后端并存时 @Autowired VectorStore 解析到这里
qdrant:
enabled: true
chroma:
enabled: true
6. 扩展与插件装配:ai.extensions.*
AiConfigAutoConfiguration 不只装配模型和网络,还把 ai4j 的扩展/插件体系自动接进 Spring。绑定入口是 AiExtensionProperties(前缀 ai.extensions),产出两个 Bean:
ExtensionRegistry:@ConditionalOnMissingBean,先ExtensionRegistry.discover()做类路径发现,再把 YAML 配置逐项应用上去。ExtensionRuntimeSnapshot:registry.snapshot()的不可变快照,供运行时读取当前启用的 tools / commands / skills / prompts / guardrails。
装配链把 YAML 的每一组配置映射成 registry 上的一次方法调用:
| YAML 配置 | registry 调用 | 含义 |
|---|---|---|
ai.extensions.enabled | enableAll(...) | 显式启用一批扩展 |
ai.extensions.explicit-resource-activation | requireExplicitResourceActivation() | 强制资源必须显式激活 |
ai.extensions.tools.expose | exposeTools(...) | 暴露哪些工具 |
ai.extensions.commands.allow | allowCommands(...) | 允许哪些命令 |
ai.extensions.skills.allow | allowSkills(...) | 允许哪些 skill |
ai.extensions.prompts.allow | allowPrompts(...) | 允许哪些 prompt |
ai.extensions.guardrails.allow | allowGuardrails(...) | 允许哪些 guardrail |
示例:
ai:
extensions:
enabled: [filesystem, search]
explicit-resource-activation: true
tools:
expose: [read-file, web-search]
skills:
allow: [summarize]
这样启动后,ExtensionRuntimeSnapshot 就是当前生效的扩展视图,业务代码不再需要自己拼装这些清单。
如果你想完全接管扩展装配(例如从企业内部的权限系统动态生成清单),直接在自己的 @Configuration 里声明同名 ExtensionRegistry Bean 即可,starter 的默认装配会自动让位。
7. Agent Blueprint 装配:ai.agent.*
当类路径上存在 ai4j-agent(starter 中以 optional 依赖引入)且 ai.agent.enabled=true 时,AgentBlueprintAutoConfiguration 会把声明的 Agent Blueprint YAML 装配成可注入的 Agent:
ai:
agent:
enabled: true
default-agent: reviewer # 注入一个默认 Agent Bean
blueprints:
reviewer: classpath:agents/reviewer.yaml
support: file:/etc/ai4j/agents/support.yaml
产出物:
AgentBlueprintLoader/AgentFactory:均为@ConditionalOnMissingBean,可被用户 Bean 接管。AgentRegistry:名字 →Agent的注册表(与AgentFlowRegistry同形态),get(name)取单个,getDefault()在default-agent指定或仅一个蓝图时可用。Agent:仅当ai.agent.default-agent设置时才暴露的默认 Bean。
模型客户端按蓝图 model.provider 从 AiServiceRegistry 解析(对应 ai.platforms[].id),协议取 model.options.protocol → ai.agent.protocol → 平台默认(anthropic 走 messages,其余走 chat)。宿主依赖——AgentToolRegistry、ToolExecutor、AgentPermissionPolicy、AgentSessionStore、AgentEventPublisher 等——都可在容器中声明为 Bean 按需注入;已启用扩展的工具、guardrail、生命周期 hook 通过 ExtensionAgentTools 与用户工具合并(不是覆盖)接入每个 Agent。
8. OkHttp SPI 扩展点
initOkHttp() 里网络栈的两个关键零件不是写死的,而是通过 SPI 加载:
ServiceLoaderUtil.load(DispatcherProvider.class) // 并发调度策略
ServiceLoaderUtil.load(ConnectionPoolProvider.class) // 连接池策略
接口定义在 io.github.lnyocly.ai4j.network:
// ai4j 2.4.2, groupId io.github.lnyo-cly
public interface DispatcherProvider {
okhttp3.Dispatcher getDispatcher();
}
public interface ConnectionPoolProvider {
okhttp3.ConnectionPool getConnectionPool();
}
默认实现是 DefaultDispatcherProvider / DefaultConnectionPoolProvider(各返回一个 new Dispatcher() / new ConnectionPool())。要替换它们,实现对应接口,并通过 Java SPI(META-INF/services/...)注册即可,整个 starter 共享的 OkHttpClient 就会走你的实现。常见用途:自定义最大并发请求、连接池存活时长、按租户隔离调度器。
9. 你应该怎么看这页
把它看成一个对象图说明页:
- 配置怎么进来
- 统一
Configuration怎么组起来 - 哪些对象是基础入口
- 哪些对象是可选增强
如果你只把它理解成“自动装配示例”,就会看漏真正重要的部分:装配顺序和失败传播路径。