1. SpringBoot的自动装配原理:

    1. 项目的启动类上会有一个@SpringBootApplication组合注解,里面包含了@EnableAutoConfiguration注解,这个注解引入了AutoConfigurationImportSelector
    2. 这个类会通过SpringFactoriesLoader从**spring-boot-autoconfigure.jar包,找一个叫META-INF/spring.factories文件中加载配置类(官方已经预定好了所有可能的成百上千个类),比如WebMvcAutoConfiguration** (SpringMVC 的配置)
    3. 这里面有很多配置类,然后会根据**@Conditional**注解进行选择性加载,比如 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) 只有项目中有Servlet类和DispatcherServlet类的时候才进行加载
    4. 但在 SpringBoot 3.x 之后,官方开始推荐使用 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件来替代 spring.factories
  2. HashMap

    1. 一个键值对存到HashMap中,怎么找到自己的桶呢?

      靠的是key的hashcode,为了防止哈希分布不均,使用了扰动处理,异或后高16位特征混合到地位中,利用(n-1)&hash算出数组的下标

    2. 哈希冲突:当链表长度大于8,且数组大于64的时候换成,红黑树(复杂度为log n),保证查找效率,(Java8)

    3. 扩容:数组默认长度为16,负载因子0.75,数量超过12就会进行扩容,容量会翻倍,所有元素要进行搬家

  3. 线程池技术:

    1. 线程池是一种池化技术,避免了频繁创建和销毁线程的开销,提高性能和响应速度
    2. 通过new ThreadPoolExecutor( 3,//核心线程数量 6,//总线程数量 60,//空闲清理线程时间 TimeUnit.SECONDS,//清理时间的单位 new ArrayBlockingQueue<>(3),//排队的队伍长度,工作队列 Executors.defaultThreadFactory(),//线程从哪里来 new ThreadPoolExecutor.AbortPolicy()//线程满了的时候的抛弃策略 );
    3. 工作一来,线程池才开始创建线程,工作完成后线程会回到线程池准备复用,如果核心线程没有空,就会进行排队,队列满了才轮到非核心线程创建
  4. 链表和数组的区别

    1. 数组:内存连续,访问快,增删慢(因为内存连续,所以如果知道了内存的大小,那么就能根据索引直接找到数据对应的内存块)
    2. 链表:内存不连续,访问非头尾节点慢,增删快
  5. @Autowired和@Resource的区别

    1. Spring官方最推荐使用构造器注入
    2. @Autowired是按照类型来进行字段注入,如果有两个类同时实现了一个接口,那么现在他就不知道该注入哪个类了
    3. @Resource是按照名称进行装配,如果没找到对应名称的Bean,那么他会报错
    4. 构造器注入的优点:
      1. 暴露循环依赖问题
      2. 避免空指针问题
      3. 更轻松的进行单元测试
      4. 容易遵循单一职责原则
    5. 可以结合lombok中的@RequiredArgsConstructors完成构造器的代码
  6. @Configuration是工厂的注解,告诉Spring这个类中有生产Bean的方法,

    @Bean是告诉Spring,把这个方法的返回值加入到IOC容器中统一管理.

    @Bean public AiCodeHelperService aiCodeHelperService(){ return AiServices.create(AiCodeHelperService.class,qwenChatModel); }

    AiServices.create底层会创建一个代理的对象,通过反射这个对象实现了AiCodeHelperService接口

  7. 这段代码采用了动态代理技术,采用了建造者模式,build()在底层返回了一个AiCodeHelperService接口实现类的对象

     AiCodeHelperService build = AiServices.builder(AiCodeHelperService.class)
                    .chatMemory(chatMemory)
                    .chatModel(qwenChatModel)
                    .build();
    
  8. 使用redis存储ChatMessage对象,langchain4j已经写好了ChatMemoryStore的接口,用来规范存,取,删数据的逻辑,只要实现它就可以了;具体的步骤

    1. AI 调用:你调 chat("你好", "user:1")
    2. 取记忆:LangChain4j 调 store.getMessages("user:1")
    3. 读 RedisredisTemplate 去 Redis 里抓那个 JSON 字符串。
    4. 反序列化:变成 List<ChatMessage> 给 AI 看。
    5. AI 回复:AI 生成回复后。
    6. 存记忆:LangChain4j 调 store.updateMessages("user:1", 新列表)
    7. 序列化:变成 JSON 字符串。
    8. 写 RedisredisTemplate 把 JSON 塞回 Redis。
  9. Ai的结构化输出:根据返回值的类型把LLM生成的Json格式字符串(langchain4j的提示词工程会使LLM生成Json格式的字符串),封装成对应的属性封装好,然后反序列化一下就变成了返回值类型的对象

  10. RAG:检索增强生成

    1. 知识库构建

      1. 首先导入pdf等文件
      2. 然后进行切片,片段大小和上下文重叠大小
      3. 进行向量化,将片段交给qwenEmbeddingModel
      4. 存到向量数据库中
    2. 检索

      1. 用户输入问题
      2. 问题被交给qwenEmbeddingModel 进行向量化
      3. 从向量数据库中拿出向量进行余弦相似度匹配

      .maxResults(5) //检索五条

      .minScore(0.75) //匹配度

    3. 增强生成 将片段合在一起变成上下文塞进提示词中交给LLM

  11. Tool Calling :

    1. LLM 想做事 -> 发指令给langchain4j -> langchain4j执行 Java 代码 -> langchain4j把结果告诉 LLM

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐