当前位置: 首页 > news >正文

三、Spring


TOP 1:Spring 中的 Bean 是线程安全的吗?

核心答案

Bean 作用域线程安全性
singleton(默认)❌ 不安全,因为多个线程共享同一个实例
prototype✅ 相对安全,每次获取都是新实例

解决方案

  1. 避免在 Bean 中定义有状态的成员变量
  2. 使用ThreadLocal存储线程局部变量
  3. 将 Bean 作用域改为prototype(不推荐,开销大)
  4. 使用不可变对象(final字段)

一句话:默认 singleton 模式下,有状态的 Bean 不安全,无状态的是安全的。


TOP 2:Spring 如何解决循环依赖?

核心答案三级缓存

缓存名称存储内容
一级singletonObjects完全初始化好的单例 Bean
二级earlySingletonObjects提前暴露的 Bean(实例化完成,未属性注入)
三级singletonFactoriesBean 工厂(用于生成代理对象)

解决流程(以 A 依赖 B,B 依赖 A 为例):

实例化 A

将 A 放入三级缓存
singletonFactories

填充 A 属性
发现依赖 B

实例化 B

将 B 放入三级缓存

填充 B 属性
发现依赖 A

从三级缓存获取 A
移到二级缓存

B 初始化完成
放入一级缓存

A 从一级缓存获取 B

A 初始化完成
放入一级缓存

注意:只能解决singleton作用域的循环依赖,prototype 无法解决。

Spring三级缓存是解决循环依赖问题的核心机制。所谓循环依赖,就是Bean A依赖Bean B,Bean B又依赖Bean A。

为什么需要三级缓存?

  • 只用一级缓存:成品和半成品混在一起,无法区分
  • 只用二级缓存:可以解决普通循环依赖,但无法处理AOP代理问题
  • 三级缓存的核心作用:通过ObjectFactory,在真正需要暴露早期对象时再决定是返回原始对象还是代理对象(避免提前创建代理,保持代理与原始对象统一)

局限

Spring的三级缓存只能解决单例模式下的setter注入循环依赖,无法解决:

  • 构造器注入的循环依赖(直接报错)
  • 多例Bean的循环依赖

TOP 3:Bean 的生命周期?

销毁阶段

执行PreDestroy标注的方法

实现DisposableBean接口的destroy方法

执行XML或Bean中指定的destroy-method

初始化阶段

执行PostConstruct标注的方法

实现InitializingBean接口的afterPropertiesSet方法

执行XML或Bean中指定的init-method

实例化 - 通过构造器创建Bean实例

属性填充 - 注入Autowired Value等依赖

Bean初始化完成 可投入使用

面试口诀

Spring Bean 的生命周期顺序为:实例化 → 属性填充 → 初始化(@PostConstruct → afterPropertiesSet → init-method)→ 使用 → 销毁(@PreDestroy → destroy → destroy-method)。


TOP 4:@Autowired 和 @Resource 的区别?

对比项@Autowired@Resource
来源Spring 原生Java 标准(JSR-250)
注入方式byType 优先byName 优先
参数requirednametype
适用框架仅 Spring任何 Java EE 容器

使用示例

// @Autowired:优先按类型匹配@AutowiredprivateUserServiceuserService;// @Resource:优先按名称匹配(name=userService)@Resource(name="userService")privateUserServiceuserService;

一句话@Autowired默认按类型填充,@Resource模型按名称填充。


TOP 5:Spring AOP 的原理是什么?

核心答案动态代理

场景代理方式条件
有接口JDK 动态代理目标类实现了接口
无接口CGLIB 动态代理目标类没有接口(生成子类)

AOP 核心概念

概念说明
JoinPoint连接点,可被增强的方法
Pointcut切入点,实际要增强的方法集合
Advice通知,增强的逻辑(@Before、@After、@Around)
Aspect切面 = Pointcut + Advice
Weaving织入,将切面应用到目标对象的过程

一句话:AOP 通过动态代理,在不修改源码的情况下给方法增强功能。

Spring 生成代理对象的时机?

是否有循环依赖生成时机
实例化后生成代理
初始化后生成代理

Spring 哪些场景会生成代理对象?

场景生成时机生成时机
普通 AOP@Aspect + @Around前置增强、后置增强
事务管理@Transactional事务提交、回滚
异步执行@Async把方法包装成任务提交给线程池
缓存管理@Cacheable @EnableCaching从缓存读取数据、数据放入缓存

Spring 创建代理失效的场景

排名失效场景出现率代码示例(❌ 失效)代码示例(✅ 正确)核心原因
1内部调用95%this.methodA()self.methodA()(注入自身代理)this指向原始对象,不经过代理
2非 public 方法80%@Transactional protected void methodA()@Transactional public void methodA()Spring 默认只代理 public 方法
3异常被 catch 吞掉70%try { ... } catch(Exception e) { log... }catch(Exception e) { throw e; }手动回滚代理感知不到异常,无法回滚
4rollbackFor 配置错误55%@Transactional(抛 checked 异常)@Transactional(rollbackFor = Exception.class)默认只回滚 RuntimeException
5final 方法45%@Transactional public final void methodA()移除final关键字CGLIB 通过子类重写,final 方法无法重写
6final 类30%@Service public final class UserService移除final关键字CGLIB 需要继承目标类,final 类无法继承

TOP 6:BeanFactory 和 FactoryBean的区别?

  • BeanFactory 是 Spring IOC 容器的根接口,定义了 getBean() 这些基础方法,它是容器本身,负责管理所有 Bean 的创建和生命周期,默认是懒加载的。
  • FactoryBean 是一个接口,开发者实现它来自定义某个复杂 Bean 的创建逻辑。FactoryBean 本身也是一个 Bean,会被 Spring 管理。创建出来的对象通过 getBean(“name”) 获取,如果想获取 FactoryBean 本身,需要用 & 前缀。
  • 常见的使用场景比如 MyBatis 的 SqlSessionFactoryBean 就是通过 FactoryBean 来生产 SqlSessionFactory 的。"

TOP 7:BeanPostProcessor 和BeanFactoryPostProcessor的区别

一句话:BeanPostProcessor 针对 Bean 实例,在 Bean 初始化前后进行增强;BeanFactoryPostProcessor 针对 BeanDefinition,在 Bean 实例化之前修改 Bean 的定义信息。

BeanDefinition有哪些信息

“BeanDefinition 是 Bean 的元数据,包含类名、作用域、构造参数、属性值、生命周期方法、懒加载、dependsOn 等信息,是 Spring 实例化 Bean 的依据。”

TOP 8:Spring 中 Bean 的作用域有哪些?

作用域说明使用场景
singleton单例(默认),容器唯一无状态 Bean
prototype原型,每次获取都新建有状态 Bean
request每个 HTTP 请求一个Web 应用
session每个 HTTP Session 一个Web 应用
application每个 ServletContext 一个Web 应用
@Scope("prototype")@ComponentpublicclassPrototypeBean{}

TOP 9:@SpringBootApplication 包含哪些注解?

核心答案:它是三个注解的组合

注解作用
@SpringBootConfiguration标注为配置类(底层是@Configuration
@EnableAutoConfiguration开启自动配置
@ComponentScan组件扫描(默认扫描当前包及子包)

等效代码

@SpringBootApplication// 等价于 ↓@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(basePackages="com.example")

TOP 10:Spring 中常用的设计模式有哪些?

设计模式Spring 中的应用
工厂模式BeanFactory、ApplicationContext
单例模式默认 Bean 作用域
代理模式AOP 动态代理
模板模式JdbcTemplate、RedisTemplate
观察者模式ApplicationListener、事件机制
适配器模式HandlerAdapter(Spring MVC)
装饰器模式BeanWrapper
策略模式InstantiationStrategy

Spring Boot 自动装配原理

一、一句话总结

Spring Boot 自动装配通过@SpringBootApplication注解中的@EnableAutoConfiguration,利用SpringFactoriesLoaderMETA-INF/spring.factories文件中加载配置类,再结合条件注解(如@ConditionalOnClass)按需生效。


高频追问链

Q: Spring 如何解决循环依赖? → (答完后)Q: 为什么需要三级缓存?两级够吗? → 两级无法处理代理对象 → Q: 什么情况下会生成代理对象? → AOP 会生成代理 → Q: AOP 的原理是什么? → 动态代理(JDK/CGLIB) → Q: JDK 和 CGLIB 有什么区别? → JDK 需要接口,CGLIB 不需要

http://www.jsqmd.com/news/952410/

相关文章:

  • 2026张家口市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 保姆级教程:用Wireshark抓包实战分析5G NAS安全模式建立全过程
  • 微信数据库AES-256-CBC解密:WechatDecrypt技术深度解析
  • STM32H743用CubeMX一键集成ThreadX,实测踩坑与避坑指南(附完整工程)
  • Linux—控制服务和守护进程
  • CPT Markets:经纪商服务体验的理性观察
  • 从ReLU到Tanh:浅层神经网络激活函数怎么选?看完这篇避坑指南再决定
  • 期货量化限价挂单总漏状态:天勤 InsertOrderTask 用法
  • 别再手动画图了!用QGIS 3.28把Excel里的气象站点数据变成专业色斑图(附数据+完整流程)
  • 【独家首发】工信部信通院联合验证的AI审核效能评估矩阵(含F1-RealTime、Bias-Delta、Audit-Traceability三项硬指标),附开源评测工具链下载链接
  • 保姆级教程:用SolidWorks 2022把CAD机械臂模型转成ROS可用的URDF文件
  • 从通信系统到振动分析:矩阵束(Matrix Pencil)方法如何成为工程界的‘瑞士军刀’?
  • 别再死记硬背了!一文搞懂正激拓扑四种复位电路(附原理动图与选型指南)
  • 2026张家界市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 实地探访深圳木点点整装:21年本土工厂,凭什么能做到84%转介绍率? - 产品测评官
  • Windows窗口管理革命:用AlwaysOnTop实现300%效率提升的终极方案
  • qorder实战:基于快马平台快速集成订单状态管理与物流跟踪接口
  • 快马ai驱动智能报告生成器,让office办公拥有大脑般的思考能力
  • 别再手动调波形了!用STM32CubeMX的DAC+定时器,5分钟生成一个244Hz的三角波
  • 律所多人协作办案的实践方法:权限管理、任务跟踪与在线协同的落地经验
  • 告别电脑开锐捷:Padavan路由器锐捷认证数据包抓取与导入全攻略(Win10实测避坑)
  • 期货多合约策略目标持仓怎么更新才不乱
  • 2026年更新:山东地区铅房施工商综合实力与推荐解析 - 2026年企业资讯
  • 手把手教你用STM32CubeMX配置TIM2通道2做输入捕获(附代码和避坑点)
  • 从core文件命名到多线程堆栈导出:一份GDB调试Linux C/C++程序的避坑指南
  • 如何用Pixelorama零基础成为像素艺术创作高手:从入门到精通的完整指南
  • 2026年北京有名的砂石分离机制造厂深度分析:如何选择可靠合作伙伴 - 2026年企业资讯
  • 别再乱装PyTorch了!手把手教你用conda搞定CUDA 10.1 + PyTorch 1.7.1黄金组合(避坑cuDNN报错)
  • 2026年近期潮州高性价比不锈钢挂衣架生产商综合解析与选择指南 - 2026年企业资讯
  • 神经渲染可编辑性:从概念到产业,一文读懂未来3D内容创作新范式