面试题--实习准备
-
SpringBoot的自动装配原理:
- 项目的启动类上会有一个
@SpringBootApplication组合注解,里面包含了@EnableAutoConfiguration注解,这个注解引入了AutoConfigurationImportSelector类 - 这个类会通过SpringFactoriesLoader从**
spring-boot-autoconfigure.jar包,找一个叫META-INF/spring.factories文件中加载配置类(官方已经预定好了所有可能的成百上千个类),比如WebMvcAutoConfiguration** (SpringMVC 的配置) - 这里面有很多配置类,然后会根据**
@Conditional**注解进行选择性加载,比如@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })只有项目中有Servlet类和DispatcherServlet类的时候才进行加载 - 但在 SpringBoot 3.x 之后,官方开始推荐使用
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件来替代 spring.factories
- 项目的启动类上会有一个
-
HashMap
-
一个键值对存到HashMap中,怎么找到自己的桶呢?
靠的是key的hashcode,为了防止哈希分布不均,使用了扰动处理,异或后高16位特征混合到地位中,利用(n-1)&hash算出数组的下标
-
哈希冲突:当链表长度大于8,且数组大于64的时候换成,红黑树(复杂度为log n),保证查找效率,(Java8)
-
扩容:数组默认长度为16,负载因子0.75,数量超过12就会进行扩容,容量会翻倍,所有元素要进行搬家
-
-
线程池技术:
- 线程池是一种池化技术,避免了频繁创建和销毁线程的开销,提高性能和响应速度
- 通过new ThreadPoolExecutor( 3,//核心线程数量 6,//总线程数量 60,//空闲清理线程时间 TimeUnit.SECONDS,//清理时间的单位
new ArrayBlockingQueue<>(3),//排队的队伍长度,工作队列 Executors.defaultThreadFactory(),//线程从哪里来 new ThreadPoolExecutor.AbortPolicy()//线程满了的时候的抛弃策略); - 工作一来,线程池才开始创建线程,工作完成后线程会回到线程池准备复用,如果核心线程没有空,就会进行排队,队列满了才轮到非核心线程创建
-
链表和数组的区别
- 数组:内存连续,访问快,增删慢(因为内存连续,所以如果知道了内存的大小,那么就能根据索引直接找到数据对应的内存块)
- 链表:内存不连续,访问非头尾节点慢,增删快
-
@Autowired和@Resource的区别
- Spring官方最推荐使用构造器注入
@Autowired是按照类型来进行字段注入,如果有两个类同时实现了一个接口,那么现在他就不知道该注入哪个类了@Resource是按照名称进行装配,如果没找到对应名称的Bean,那么他会报错- 构造器注入的优点:
暴露循环依赖问题避免空指针问题更轻松的进行单元测试容易遵循单一职责原则
- 可以结合lombok中的@RequiredArgsConstructors完成构造器的代码
-
@Configuration是工厂的注解,告诉Spring这个类中有生产Bean的方法,
@Bean是告诉Spring,把这个方法的返回值加入到IOC容器中统一管理.
@Bean public AiCodeHelperService aiCodeHelperService(){ return AiServices.create(AiCodeHelperService.class,qwenChatModel); }AiServices.create底层会创建一个代理的对象,通过反射这个对象实现了AiCodeHelperService接口
-
这段代码采用了动态代理技术,采用了建造者模式,build()在底层返回了一个AiCodeHelperService接口实现类的对象
AiCodeHelperService build = AiServices.builder(AiCodeHelperService.class) .chatMemory(chatMemory) .chatModel(qwenChatModel) .build(); -
使用redis存储ChatMessage对象,langchain4j已经写好了ChatMemoryStore的接口,用来规范存,取,删数据的逻辑,只要实现它就可以了;具体的步骤
- AI 调用:你调
chat("你好", "user:1")。 - 取记忆:LangChain4j 调
store.getMessages("user:1")。 - 读 Redis:
redisTemplate去 Redis 里抓那个 JSON 字符串。 - 反序列化:变成
List<ChatMessage>给 AI 看。 - AI 回复:AI 生成回复后。
- 存记忆:LangChain4j 调
store.updateMessages("user:1", 新列表)。 - 序列化:变成 JSON 字符串。
- 写 Redis:
redisTemplate把 JSON 塞回 Redis。
- AI 调用:你调
-
Ai的结构化输出:根据返回值的类型把LLM生成的Json格式字符串(langchain4j的提示词工程会使LLM生成Json格式的字符串),封装成对应的属性封装好,然后反序列化一下就变成了返回值类型的对象
-
RAG:检索增强生成
-
知识库构建
- 首先导入pdf等文件
- 然后进行切片,片段大小和上下文重叠大小
- 进行向量化,将片段交给
qwenEmbeddingModel - 存到向量数据库中
-
检索
- 用户输入问题
- 问题被交给
qwenEmbeddingModel进行向量化 - 从向量数据库中拿出向量进行余弦相似度匹配
.maxResults(5) //检索五条.minScore(0.75) //匹配度 -
增强生成 将片段合在一起变成上下文塞进提示词中交给LLM
-
-
Tool Calling :
- LLM 想做事 -> 发指令给langchain4j -> langchain4j执行 Java 代码 -> langchain4j把结果告诉 LLM
更多推荐



所有评论(0)