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,它是启动类上的复合注解。

相关推荐
nanxun8864 小时前
记一次诡异的 Docker 容器"串包"故障排查
java
用户1563068103517 小时前
Day01 | Java 基础(Java SE)
java
行者全栈架构师8 小时前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师12 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_012 小时前
mac(m5)平台编译openjdk
java
唐青枫1 天前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马2 天前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261352 天前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
用户3721574261352 天前
Java 打印 Word 文档:从基础打印到高级设置
java
用户3521802454752 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程