云
2026-10-25 4229657c5b6be8a1da9e59a40e2426cf6b0995c2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package cn.iocoder.yudao.server;
 
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
 
/**
 * 项目的启动类
 *
 * 如果你碰到启动的问题,请认真阅读 https://doc.iocoder.cn/quick-start/ 文章
 * 如果你碰到启动的问题,请认真阅读 https://doc.iocoder.cn/quick-start/ 文章
 * 如果你碰到启动的问题,请认真阅读 https://doc.iocoder.cn/quick-start/ 文章
 *
 * @author 超级管理员
 */
@Slf4j
@SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package}
@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}.server", "${yudao.info.base-package}.module"},
        // 注意:这里排除的 Spring AI 自动配置,与各 profile 的 spring.autoconfigure.exclude 保持一致,但写在代码里的
        // 原因是:注解里的排除项与 yaml 里的排除项是「并集」,不会被外部 profile 配置文件覆盖,保证换任何 profile 都能正常启动。
        // 1. 向量库:AI 模块由 AiModelFactoryImpl 手动构建 VectorStore,三个自动配置同时启用会争抢 vectorStore 这个 bean 名
        // 2. 模型:AI 模块的模型由 AiModelFactoryImpl 手动构建(走 DB 里 ai_model 配置的 apiKey),不需要 Spring AI 的模型 Bean;
        //    且未配置 api-key 时自动配置会在启动阶段直接抛「API key cannot be empty.」
        excludeName = {
                // ========== 向量库自动配置 ==========
                "org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration",
                "org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration",
                "org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration",
                // ========== 模型自动配置 ==========
                "org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration",
                "org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration",
                "org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration",
                "org.springframework.ai.model.openai.autoconfigure.OpenAiAudioSpeechAutoConfiguration",
                "org.springframework.ai.model.openai.autoconfigure.OpenAiAudioTranscriptionAutoConfiguration",
                "org.springframework.ai.model.openai.autoconfigure.OpenAiModerationAutoConfiguration",
                "org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration",
                "org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration",
                "org.springframework.ai.model.google.genai.autoconfigure.chat.GoogleGenAiChatAutoConfiguration",
                "org.springframework.ai.model.google.genai.autoconfigure.embedding.GoogleGenAiEmbeddingConnectionAutoConfiguration",
                "org.springframework.ai.model.google.genai.autoconfigure.embedding.GoogleGenAiTextEmbeddingAutoConfiguration",
                "org.springframework.ai.model.ollama.autoconfigure.OllamaApiAutoConfiguration",
                "org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration",
                "org.springframework.ai.model.ollama.autoconfigure.OllamaEmbeddingAutoConfiguration",
                "org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration",
        })
public class YudaoServerApplication {
 
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
 
        SpringApplication app = new SpringApplication(YudaoServerApplication.class);
        app.setApplicationStartup(new BufferingApplicationStartup(4096));
        app.run(args);
 
        long cost = System.currentTimeMillis() - startTime;
        log.info("========================================");
        log.info("应用启动完成,耗时: {} 秒 ({} 毫秒)", cost / 1000.0, cost);
        log.info("========================================");
    }
 
}