SSM拷打第二讲!!!

7. Spring中的循环引用?

复制代码
是什么->能解决的是什么->三级缓存

Spring 的循环依赖就是 Bean 之间互相依赖,比如 A 依赖 B,B 又依赖 A。

Spring 能解决的主要是单例 Bean 的属性注入循环依赖。它的核心思路是:A 实例化之后,还没完成属性填充和初始化,就先把 A 的早期引用暴露出来;这时 B 创建时需要 A,就可以先拿到这个早期引用,等 B 创建完再回头完成 A 的注入。

三级缓存里,一级缓存放完整 Bean,二级缓存放早期 Bean,三级缓存放 ObjectFactory。三级缓存的意义主要是为了在有 AOP 的情况下,能提前拿到代理对象,避免注入原始对象。

但构造器循环依赖和原型 Bean 循环依赖解决不了,因为它们没法像单例属性注入那样提前暴露引用。

8. 那具体解决流程清楚吗?

Spring 解决单例属性注入循环依赖,大概流程可以用 A、B 互相依赖来理解。

创建 A 的时候,Spring 会先把 A 实例化出来,但这时 A 还没有完成属性注入和初始化。为了避免后面别人依赖 A 时拿不到对象,Spring 会把一个能获取 A 早期引用的 ObjectFactory 放到第三级缓存里。

接着 A 做属性填充,发现需要 B,就去创建 B。B 也会先实例化,并且提前暴露。然后 B 属性填充时发现需要 A,这时候 Spring 会从 A 的第三级缓存里拿到 ObjectFactory,通过它拿到 A 的早期引用,放到二级缓存,并注入给 B。

B 完成初始化后进入一级缓存。然后回到 A,A 就可以注入已经创建好的 B,最后 A 也完成初始化,进入一级缓存,同时清理之前的早期引用缓存。

这里要注意,ObjectFactory 不是重新创建 A,而是返回 A 的早期引用;如果 A 需要 AOP,它返回的可能就是代理对象。

9. 构造方法出现了循环依赖怎么解决?

构造器循环依赖 Spring 默认是解决不了的。比如 A 的构造方法需要 B,B 的构造方法又需要 A,这时候 A 和 B 都还没实例化完成,Spring 没有任何一个早期对象可以提前暴露,所以三级缓存也救不了。

解决上,我一般不会优先想着硬绕过去,而是先看是不是设计有问题,比如把互相依赖的逻辑抽到第三个服务里,或者重新拆分职责。如果只是技术上要临时打破这个循环,可以用 @Lazy,让其中一个依赖注入懒加载代理对象;也可以改成 Setter 或字段注入,让对象先实例化出来,再做属性填充。但从设计上看,构造器循环依赖通常是不太好的信号。

10. SpringMVC的执行流程?

SpringMVC = Java 后端接收请求、调用 Controller、返回响应的框架。

SpringMVC 的核心入口是 DispatcherServlet。请求进来后,先由 DispatcherServlet 接收,然后通过 HandlerMapping 找到对应的 Controller 方法,同时拿到相关拦截器。

接着 DispatcherServlet 会交给 HandlerAdapter 去真正调用 Controller。在这个过程中,SpringMVC 会完成参数解析、数据绑定、类型转换这些工作。Controller 执行完之后会返回结果。

如果是传统页面请求,返回的可能是 ModelAndView,然后通过 ViewResolver 解析视图,最后渲染页面返回给浏览器。

如果是现在常见的 REST 接口,比如 @RestController,一般不会走视图解析,而是通过 HttpMessageConverter 把返回对象转成 JSON,再写回响应体。

11. Springboot自动配置原理

Spring Boot 自动配置的入口一般是 @SpringBootApplication,它里面包含了 @EnableAutoConfiguration,这个是自动配置的核心。

@EnableAutoConfiguration 会通过 @Import 导入 AutoConfigurationImportSelector,然后去加载自动配置类清单。老版本主要是从 META-INF/spring.factories 里读,Spring Boot 3 之后主要是从 AutoConfiguration.imports 里读。

这些自动配置类不会无脑生效,而是会配合很多条件注解判断,比如 classpath 里有没有某个类、用户有没有自己定义 Bean、配置文件里有没有开启某个属性。只有条件满足时,Spring Boot 才会把对应的 Bean 注册到容器里。

12. Spring 的常见注解有哪些?

Spring 常见注解我一般按使用场景来分。

第一类是 Bean 注册,比如 @Component,以及它的语义化扩展 @Service@Repository@Controller

第二类是依赖注入,比如 @Autowired@Resource@Qualifier

第三类是配置相关,比如 @Configuration@Bean@ComponentScan

第四类是 Web 开发里常用的,比如 @RestController@RequestMapping@GetMapping@PostMapping@RequestBody@ResponseBody。还有事务相关的 @Transactional,AOP 相关的 @Aspect@Around@Pointcut

如果是 Spring Boot 项目,还会常用 @SpringBootApplication,它是启动类上的复合注解。

相关推荐
小江的记录本1 小时前
【JVM虚拟机】类加载机制:类加载全流程:加载→验证→准备→解析→初始化(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·算法·安全·spring·面试
J2虾虾1 小时前
Spring AI Alibaba - Models 模型
人工智能·spring·microsoft
千纸鹤の脉搏1 小时前
多线程的初步了解---进程与线程
java·开发语言·学习·线程
许彰午2 小时前
状态模式实战——Row对象的状态机
java·ui·状态模式
搬石头的马农2 小时前
Claude Code SpringBoot开发:从0到1搭建企业级项目的6个核心Skill
java·人工智能·spring boot·后端·ai编程
西安邮电大学2 小时前
Redis为什么快?
java·redis·后端·其他·面试
折哥的程序人生 · 物流技术专研2 小时前
《Java 100 天进阶之路》第39篇:Java泛型方法的定义和使用
java·开发语言·后端·面试·求职招聘
土狗TuGou2 小时前
SQL内功笔记 · 第6篇:窗口函数的使用ROW_NUMBER等
java·数据库·后端·sql·mysql
Chase_______2 小时前
【Java基础核心知识点全解·09】Java 内存布局与垃圾回收详解:栈、堆、栈帧、GC Roots 与对象回收
java·开发语言