学习学习学习

微服务相关?

1. 什么是微服务?它的核心思想是什么?

  • 微服务:一种架构风格,将一个庞大的单体应用,拆分成多个小型、独立、可部署的服务,每个服务聚焦一个具体的业务模块,服务之间通过轻量级通信协议(如 HTTP、RPC)交互,独立开发、独立部署、独立维护。

  • 核心思想:拆分巨石应用,实现高内聚、低耦合 ------ 每个服务只负责自己的业务,不依赖其他服务的内部实现,降低开发、测试、部署的复杂度,提升系统的可扩展性和容错性

2. 微服务和单体架构的区别是什么?

  • 单体架构:所有业务模块(如用户、订单、商品)都打包在一个应用中,部署在一个服务器上,开发简单、部署方便,但耦合度高、扩展性差,一个模块故障可能导致整个应用崩溃。
  • 微服务架构:拆分多个独立服务,每个服务对应一个业务模块,单独部署、单独扩容,耦合度低、扩展性强,一个服务故障不影响其他服务,但开发、部署、运维复杂度提升。
  • 核心区别:是否拆分服务、耦合度高低、扩展性强弱、运维复杂度。
对比维度 单体架构 微服务架构
架构特点 所有模块集中在一个应用内 按业务拆分为多个独立服务
耦合度 高耦合,模块间依赖强 低耦合,服务间通过轻量协议通信
扩展性 整体扩容,难以针对模块单独扩展 可针对单个服务独立扩容
部署方式 单次部署整个应用 各服务可独立部署、上线
故障影响 一个模块故障可能导致整体宕机 单个服务故障不影响其他服务
开发运维 开发简单,运维成本低 开发、部署、运维复杂度高,需配套工具

微服务更适合业务快速迭代、高并发的场景,单体更适合业务简单、快速上线的小型项目

3.微服务的优势和缺点是什么?

优势:

  • 低耦合:服务独立,互不依赖内部实现,修改一个服务不影响其他服务。
  • 高扩展性:单个服务可根据业务需求独立扩容(如订单服务高峰期单独加机器)。
  • 容错性强:一个服务故障,不会导致整个系统崩溃,可通过降级、熔断避免连锁反应。
  • 开发高效:多团队并行开发,每个团队负责一个服务,提升开发效率。

缺点:

  • 运维复杂:多个服务独立部署、监控、维护,需要额外的运维工具和成本。
  • 分布式问题:服务之间通信存在网络延迟、超时、分布式事务等问题。
  • 调试困难:跨服务问题排查复杂,需要追踪整个调用链路。

4.微服务核心组件?

微服务架构中,常用的核心组件有哪些?各自作用是什么?

服务注册与发现

核心组件:Eureka、Consul、Nacos(常用 Nacos,易部署、功能全)。

作用:服务启动时,自动注册到注册中心,其他服务通过注册中心获取服务地址,无需手动配置服务地址,解决 "服务地址动态变化" 问题。

组件类别 常用组件 核心作用
服务注册与发现 Eureka、Consul、ZooKeeper、Nacos 管理所有服务的实例地址,实现服务自动注册、健康检查和动态发现,解决服务地址变化问题
配置中心 Spring Cloud Config、Nacos 集中管理所有服务的配置,支持配置动态刷新,避免配置文件分散和修改重启服务的问题
服务网关 Zuul、Spring Cloud Gateway 作为系统统一入口,实现路由转发、权限校验、限流、日志统计,隔离内外网,简化客户端调用
服务调用 / 通信 RestTemplate、OpenFeign、Dubbo、 实现服务之间的远程调用,支持负载均衡,简化跨服务接口调用代码编写
熔断与限流 Hystrix、Sentinel 防止服务雪崩,当某个服务故障时快速熔断降级,保护上游服务,提升系统容错能力
链路追踪 Zipkin、pinpoint 追踪跨服务调用的完整链路,记录请求耗时、调用关系,快速定位分布式系统中的性能瓶颈和故障
API 网关:
  • 核心组件:Gateway、Zuul(常用 Gateway,基于 Spring Boot,性能好)。
  • 作用:统一入口,所有客户端请求都经过网关,实现路由转发、权限校验、限流、熔断、日志监控等功能,简化客户端调用。
服务通信:
  • 核心方式:HTTP 协议(RESTful API,简单易懂,跨语言)、RPC 协议(Dubbo、Feign+Spring Cloud LoadBalancer,Feign 基于 HTTP,Dubbo 基于 RPC,性能高,适合 Java 内部服务通信)。
  • 作用:实现不同微服务之间的数据交互和调用。
配置中心:
  • Nacos、Nacos,兼顾注册中心和配置中心。
  • 作用:集中管理所有微服务的配置(如数据库地址、端口、参数),支持配置动态刷新,无需重启服务即可更新配置。
什么是服务注册与发现?Nacos 的核心作用是什么?
  • 服务注册:微服务启动时,将自己的服务名称、IP 地址、端口等信息,注册到注册中心(如 Nacos),注册中心维护一个服务列表。
  • 服务发现:当服务 A 需要调用服务 B 时,先从注册中心查询服务 B 的地址,再通过该地址调用服务 B,无需手动配置服务 B 的地址。
  • Nacos 核心作用:① 服务注册与发现(核心);② 配置中心(集中管理配置,动态刷新);③ 服务健康监测(检测服务是否可用,剔除故障服务)。
API 网关的核心功能有哪些?
  • 路由转发 :将客户端请求,根据请求路径转发到对应的微服务(如/api/user转发到用户服务,/api/order转发到订单服务)。
  • 权限校验:统一拦截所有请求,校验用户 Token、权限,拒绝非法请求,无需每个服务单独实现权限校验。
  • 限流熔断:限制客户端请求频率,避免服务被高并发压垮;当目标服务故障时,熔断调用,返回默认数据,避免连锁故障。
  • 日志监控:记录所有请求的详细信息(请求路径、响应时间、状态码),便于问题排查和性能分析
微服务服务治理?

什么是服务熔断、服务降级?两者的区别是什么?

  • 服务熔断:当一个服务出现频繁故障、超时,为了避免影响其他服务,暂时 "断开" 对该服务的调用,返回默认数据或提示,等待服务恢复后再重新调用(类似电路熔断,防止故障扩散)。

    • 核心目的:防止故障连锁反应,保护整个微服务系统。
  • 服务降级:当系统处于高并发、资源紧张时,暂时关闭一些非核心服务的功能(如积分兑换、历史订单查询),优先保证核心服务(如支付、下单)正常运行,降低系统负载。

    • 核心目的:保证核心服务可用,牺牲非核心功能。
  • 区别:熔断是 "被动触发"(服务故障导致),降级是 "主动触发"(高并发、资源紧张导致)。

什么是负载均衡?微服务中如何实现负载均衡?
  • 负载均衡:当一个服务部署多个实例(如订单服务部署 3 台机器),客户端请求会均匀分配到各个实例,避免单个实例压力过大,提升服务的可用性和并发能力。

  • 微服务中实现方式(常用 2 种)

    • 客户端负载均衡:Feign+Spring Cloud LoadBalancer(Spring Cloud 官方推荐,替代 Ribbon),客户端调用服务时,从注册中心获取服务实例列表,自己决定调用哪个实例(如轮询、随机)。
    • 服务端负载均衡:API 网关(如 Spring Cloud Gateway),所有请求经过网关,由网关将请求分配到不同的服务实例。
微服务中的分布式事务问题是什么?如何解决?
  • 分布式事务问题:多个微服务之间的事务操作,无法保证原子性(如用户下单:订单服务创建订单,库存服务扣减库存,支付服务扣减余额,若其中一个服务失败,其他服务已执行的操作无法回滚,导致数据不一致)。

  • 解决方法

    • 最终一致性方案(主流):基于消息队列(如 RabbitMQ、RocketMQ)实现,采用 "本地事务 + 消息通知" 的方式,确保所有服务最终执行成功(如订单创建成功后,发送消息通知库存和支付服务,失败则重试)。
    • 简化方案:使用 Seata 框架(阿里开源),封装了分布式事务的实现,只需简单配置,即可实现分布式事务的原子性
什么是服务链路追踪?常用组件是什么?
  • 服务链路追踪:当一个客户端请求经过多个微服务(如请求下单→订单服务→库存服务→支付服务),追踪整个请求的调用链路,记录每个服务的调用时间、状态,便于排查跨服务的问题(如请求超时,定位是哪个服务耗时过长)。

  • 常用组件:Sleuth+Zipkin(Spring Cloud 常用),Sleuth 负责生成追踪 ID,标记调用链路;Zipkin 负责收集追踪数据,可视化展示调用链路。

5.微服务高频框架(Spring Cloud/Spring Boot)

Spring Boot 和 Spring Cloud 的关系是什么?

  • Spring Boot:一款快速开发框架,简化 Spring 应用的配置和部署("约定大于配置"),可快速创建独立的 Spring 应用,是微服务开发的基础(每个微服务都是一个 Spring Boot 应用)。

  • Spring Cloud:基于 Spring Boot,提供了微服务架构所需的核心组件(服务注册发现、网关、Spring Cloud LoadBalancer 负载均衡等),是一套微服务解决方案,用于整合多个 Spring Boot 应用,构建完整的微服务系统。

  • 关系:Spring Boot 是基础,Spring Cloud 是在 Spring Boot 之上的微服务整合框架,没有 Spring Boot 就没有 Spring Cloud,Spring Cloud 依赖 Spring Boot 实现微服务的开发和部署

  • Spring Boot:是一个快速开发单体应用的脚手架,通过自动配置简化了 Spring 应用的搭建和开发,让你可以快速创建独立运行的 Java 应用。
  • Spring Cloud:是一套基于 Spring Boot 实现的微服务治理框架,提供了服务注册与发现、配置中心、网关、负载均衡、熔断限流等微服务所需的组件和解决方案。
  • 两者关系 :Spring Cloud 依赖 Spring Boot,它的所有组件都是基于 Spring Boot 开发的;Spring Boot 是 Spring Cloud 的基础,Spring Cloud 是 Spring Boot 在微服务场景下的扩展。简单来说,Spring Boot 用于开发单个微服务,Spring Cloud 用于管理多个微服务

Spring Cloud 常用组件有哪些?


  • 服务注册与发现:Nacos/Eureka(Nacos 更常用,兼容 Eureka,支持配置中心)。
  • API 网关:Spring Cloud Gateway(替代 Zuul,性能更好,基于 Netty)。
  • 服务通信:Feign(基于 HTTP,声明式调用,简化服务调用)、Dubbo(基于 RPC,性能高)。
  • 负载均衡:Spring Cloud LoadBalancer(Spring Cloud 官方推荐,替代 Ribbon,配合 Feign 使用,实现客户端负载均衡)。
  • 熔断降级:Sentinel(阿里开源,替代 Hystrix,实现熔断、降级、限流)。
  • 配置中心:Nacos(Nacos 兼顾注册中心,部署简单)。

Feign 和 Dubbo 的区别是什么?

  • 通信协议:Feign 基于 HTTP 协议(RESTful API),跨语言、简单易懂;Dubbo 基于 RPC 协议,性能更高,仅适用于 Java 语言。
  • 开发复杂度:Feign 是声明式调用,只需编写接口和注解,开发简单;Dubbo 需要配置服务接口、注册中心,开发略复杂。
  • 适用场景:Feign 适合跨语言、服务之间通信频率不高的场景;Dubbo 适合 Java 内部服务、高并发、高性能要求的场景。
对比维度 Feign Dubbo
通信协议 HTTP(RESTful) RPC
跨语言支持 支持 仅 Java
性能 一般
开发方式 声明式接口 + 注解,简单 需配置服务接口、注册中心,略复杂
适用场景 跨语言调用、通信频率不高 Java 内部服务、高并发高性能场景
微服务拆分的原则是什么?
  • 单一职责原则:每个服务只负责一个核心业务模块(如用户服务只处理用户相关操作,订单服务只处理订单相关操作)。
  • 高内聚、低耦合:服务内部功能紧密相关,服务之间尽量减少依赖,仅通过接口交互。
  • 避免过度拆分:拆分过细会导致服务数量过多,运维、通信成本增加(如不要把 "用户查询" 和 "用户修改" 拆分成两个服务)。
  • 按业务域拆分:以业务领域为边界(DDD 领域驱动设计思想),比如电商系统可拆分为用户域、订单域、支付域、商品域等,每个服务对应一个独立的业务域。
  • 避免过度拆分:拆分粒度要适中,过细的拆分会导致服务间调用链路过长、运维复杂度陡增,反而得不偿失。
  • 数据独立自治:每个微服务应拥有自己独立的数据库,避免跨服务直接访问数据库,保证数据的内聚性和一致性。
  • 面向接口而非实现:服务间仅通过公开接口交互,隐藏内部实现细节,避免服务间的强依赖。
微服务中,服务之间为什么不能直接调用,要通过 API 网关?
  • 统一入口:客户端无需记住多个服务的地址,只需调用网关地址,由网关转发,简化调用。
  • 统一管控:所有请求都经过网关,可统一实现权限校验、限流、熔断、日志监控,无需每个服务单独实现,降低开发成本。
  • 隐藏服务细节:客户端无需知道服务的部署地址、实例数量,服务升级、扩容时,客户端无需修改任何配置。
Nacos 和 Eureka 的区别是什么?
  • 功能:Nacos 支持服务注册发现、配置中心、服务健康监测,功能更全面;Eureka 仅支持服务注册发现。
  • 可用性:Nacos 支持 AP/CP 模式切换(默认 AP,保证可用性);Eureka 仅支持 AP 模式,注重可用性。
  • 部署:Nacos 部署简单,支持单机、集群模式;Eureka 需要单独部署,集群配置较复杂。
  • 现状:Eureka 已停止更新,Nacos 是 Spring Cloud Alibaba 推荐组件,目前更常用。
对比维度 Nacos Eureka
核心功能 服务注册发现 + 配置中心 + 健康监测 仅服务注册发现
一致性模式 支持 AP/CP 切换 仅支持 AP
部署复杂度 简单,支持一键启动 较复杂,需手动配置集群
社区活跃度 活跃,持续更新维护 已停止更新
Spring Cloud 支持 Spring Cloud Alibaba 推荐组件 Spring Cloud 早期默认组件

微服务中的 "雪崩效应" 是什么?如何避免?

雪崩效应:一个核心服务故障,导致依赖该服务的其他服务也相继故障,最终导致整个微服务系统崩溃(如支付服务故障,导致订单、库存、用户服务都无法正常运行)。

避免方法

  • 熔断:给服务添加熔断机制(如 Sentinel),故障时断开调用,避免故障扩散。
  • 降级:高并发时,降级非核心服务,保证核心服务可用。
  • 限流:通过 API 网关或 Sentinel 限制客户端请求频率,避免服务被高并发压垮。
  • 服务集群:核心服务部署多个实例,配合 Spring Cloud LoadBalancer 实现负载均衡,避免单点故障。
  • 服务熔断:当依赖的服务故障率达到阈值时,快速熔断,直接返回降级结果,避免持续等待造成线程资源耗尽。
  • 服务降级:高并发或故障时,暂时关闭非核心功能,优先保证核心服务可用。
  • 限流控制:限制请求频率,防止超出系统承载能力,避免服务被压垮。
  • 超时与重试机制:设置合理的调用超时时间,避免线程被长时间占用;同时限制重试次数,防止请求风暴。
  • 异步调用:使用消息队列进行解耦,避免同步调用链路过长导致的级联故障。
  • 资源隔离:不同服务的调用使用独立的线程池,避免单个服务故障拖垮整个应用。

Java 锁

解决多线程并发安全问题的核心机制,用来控制多个线程同时访问共享资源时的冲突,避免数据错乱、线程安全问题。

作用:修饰方法、代码块,保证同一时间只有一个线程执行。

Java 分布式锁

作用:修饰方法、代码块,保证同一时间只有一个线程执行。

分布式锁是解决分布式系统中多服务 / 多进程并发安全 的核心方案,解决:同一个服务部署在多台机器上,同时操作共享资源(如扣库存、生成订单)导致的数据错乱问题

和本地锁(synchronized/Lock)最大区别:

  • 本地锁:只锁当前 JVM 进程,分布式环境无效
  • 分布式锁:锁整个集群 / 全局 ,跨机器、跨服务生效
  1. 为什么本地锁(synchronized/ReentrantLock)不能用于分布式场景?

答案 :本地锁作用域仅限单个 JVM 进程,分布式系统中服务部署在多台机器 / 多个进程,不同进程的锁相互隔离,无法实现全局互斥,因此失效。

  1. 分布式锁需要满足哪些核心特性?
  • 互斥性:同一时刻仅一个客户端持有锁;
  • 防死锁:锁必须设置过期时间,客户端宕机也能自动释放;
  • 安全性:只能释放自己持有的锁,防止误删;
  • 高可用:加锁、解锁操作不能因中间件故障大面积失效;
  • 高性能:加解锁开销小,支撑高并发;
  • 可选:支持可重入、阻塞等待、锁续期。

3. 主流分布式锁实现方案有哪些?各自优缺点?

答案

  1. Redis 分布式锁
    • 优点:性能高、实现简单、社区成熟,适配绝大多数业务;
    • 缺点:主从异步复制可能短暂丢锁,强一致性弱于 Zookeeper。
  2. Zookeeper 分布式锁
    • 优点:基于临时节点 + 监听机制,强一致性、天然防死锁、无需手动续期;
    • 缺点:性能偏低,集群部署重,高并发场景不占优。
  3. MySQL 分布式锁
    • 优点:零额外组件,实现最简单;
    • 缺点:性能差、数据库压力大、容易出现死锁,仅适用于低并发简单场景。

4.手写 Redis 分布式锁,为什么要用 SET key value NX PX 一条命令?分开写行不行?

答案 : 不行。set+expire 是两条命令,不具备原子性。 如果执行完set后服务宕机,锁永远无法过期 ,引发死锁。 SET NX PX 是 Redis 原子命令,加锁 + 设置过期一步完成,彻底规避该问题。

  • NX:key 不存在才设置,保证互斥;
  • PX:毫秒级过期,防死锁。

性能指标

一、系统性能核心指标

  1. QPS(Queries Per Second)每秒查询率

定义:每秒服务器可响应的查询请求数,偏向读请求。

适用:列表查询、页面访问、纯查询接口。

特点:单次逻辑简单、耗时短。

  1. TPS(Transactions Per Second)每秒事务数

定义:每秒完成的完整业务事务数,偏向写请求。

事务:一次完整业务流程,包含多次读写、接口调用、数据变更。

适用:下单、支付、数据提交、增删改业务。

特点:链路长、资源消耗大,同场景下 TPS 通常低于 QPS。

  1. 吞吐量

广义概念,分两类:

请求吞吐量:统计每秒总请求数,和 QPS 口径接近;

数据吞吐量:单位时间传输数据大小 (KB/s、MB/s),多用于文件、流媒体。

配套监控指标

响应时间 RT、并发数、错误率、CPU / 内存 / 磁盘 IO / 网络 IO、数据库连接数。

吞吐量 = 单位时间里,系统成功处理 / 通过的数据、任务、产品总量 简单一句话:单位时间能干完多少活

1. 网络 / 通信(最常用)

每秒成功传输的数据量,单位:bps、MB/s、Gbps

例:宽带吞吐量 100MB/s = 每秒实际传 100 兆数据(≠带宽标称,受损耗影响)

2. 计算机 / 服务器 / 接口

单位时间处理请求数,常用:TPS(每秒事务数)、QPS(每秒查询数)

例:接口吞吐量 5000QPS = 接口一秒能正常扛 5000 次访问

3. 生产 / 物流 / 工厂

单位时间产出成品 / 转运货物数量

例:流水线日吞吐量 5000 件 = 一天生产 5000 个产品

4. 硬盘 / 存储

每秒读写数据大小,MB/s

固态硬盘吞吐量 5000MB/s:一秒读写 5000 兆数据

缓存三大问题

缓存穿透、缓存击穿、缓存雪崩

整体场景:请求优先查询缓存,缓存无数据再查询数据库。

(一)缓存穿透

定义:查询缓存、数据库都不存在的数据,无效请求全部直达数据库。

成因:恶意请求非法参数、业务查询无结果数据。

解决方案:

空值缓存:查询为空时,缓存空数据,设置较短过期时间;

参数校验:网关 / 接口拦截非法 ID、格式异常请求;

布隆过滤器:前置过滤非法 Key,海量数据场景优选;

限流:对异常 IP、高频无效请求做流量限制。

(二)缓存击穿

定义:单个热点 Key过期,瞬时大量并发请求直接打到数据库。

成因:秒杀、爆款、首页等高访问热点数据统一过期。

解决方案:

分布式互斥锁:仅一个请求查询数据库并更新缓存,其余请求等待;

热点 Key 永不过期:代码异步定时刷新数据,规避过期问题;

逻辑过期:存储逻辑过期时间,过期后异步更新缓存,旧数据正常返回。

(三)缓存雪崩

定义:大批量缓存 Key 同时失效 或 Redis 整体宕机,海量请求压垮数据库。

成因:Key 过期时间集中、Redis 集群故障、服务资源耗尽。

解决方案:

过期时间加随机值,打散批量失效;

Redis 做集群 + 哨兵,实现高可用,避免单点故障;

多级缓存:本地缓存 + 分布式缓存,层层兜底;

限流、熔断、降级:缓存异常时拒绝流量,返回兜底数据;

线程池隔离:隔离缓存、数据库请求,防止故障扩散。

快速区分口诀

穿透:查不存在的数据 → 无效请求打 DB

击穿:单个热点 Key 失效 → 高并发单点打 DB

雪崩:批量 Key 失效 / 缓存宕机 → 全量流量打 DB

谈谈你对线程的理解?

线程是 CPU 调度和执行的最小单位,一个进程里可以有多个线程,它们共享进程内存,同时执行不同任务,从而提高程序效率和响应速度。

  • 进程:一个正在运行的程序(比如一个 Java 应用)
  • 线程:程序里真正干活的 "执行小路"

进程 vs 线程

  • 进程有独立内存空间,相互隔离;
  • 线程共享进程内存(堆、方法区),只私有栈、程序计数器;
  • 进程切换开销大,线程切换开销小;
  • 多进程是 "多个程序同时跑",多线程是 "一个程序里多段代码同时跑"。

线程的生命周期

  • 新建(New):new Thread (),还没 start
  • 就绪(Runnable):调用 start (),等待 CPU 时间片
  • 运行(Running):获得 CPU,执行 run ()
  • 阻塞(Blocked):等待锁、IO、sleep 等
  • 等待(Waiting):wait()、join()、LockSupport.park()
  • 终止(Terminated):run 执行完毕或异常退出

线程从新建,start()后进入就绪,抢到 CPU 时间片进入运行;遇到同步锁、sleep/wait/park等操作进入阻塞 / 等待;任务执行完毕或异常退出后线程终止。

Java 创建线程的 4 种方式详解

继承Thread

实现Runnable接口(无返回值)

实现Callable接口(有返回值、可抛出受检异常)

使用线程池(ThreadPoolExecutor/Executors)✅企业主流

  • start()run()区别:start()真正创建操作系统线程、进入就绪;直接调用run()只是普通方法调用,不会新开线程。
  • 线程池是项目开发首选,前三种多用于临时简单测试场景。

线程常用方法

  • start():启动线程,进入就绪态
  • run():承载业务逻辑
  • sleep(long):线程休眠,不释放锁
  • wait():进入等待,释放锁 ,依靠notify/notifyAll唤醒
  • notify()/notifyAll():唤醒处于等待的线程
  • join():线程插队执行,等待目标线程执行完毕后当前线程再继续
  • yield():让出 CPU 使用权,线程退回就绪态

多线程带来的问题与解决

多线程核心问题:原子性、可见性、有序性缺失 → 引发线程不安全、数据错乱

解决方案:

  1. synchronized:内置同步锁,可保证原子性、可见性、有序性
  2. Lock:以ReentrantLock为代表,锁操作更灵活
  3. volatile:保证可见性、禁止指令重排,无法保证原子性
  4. ThreadLocal:变量线程私有化,规避多线程共享竞争
  5. 线程安全集合:ConcurrentHashMapCopyOnWriteArrayList

一、手动创建线程弊端

  • 频繁创建销毁开销大
  • 线程不可控,容易 OOM

二、线程池优势

  • 复用线程
  • 控制并发数量
  • 统一管理、配置拒绝策略

三、线程池核心参数

核心线程数、最大线程数、阻塞队列、空闲存活时间、线程工厂、拒绝策略

总结:

  • 线程是 CPU 调度最小单位,共享进程内存,提升并发效率。
  • 线程生命周期:新建→就绪→运行→阻塞 / 等待→终止。
  • 创建线程 4 种方式:继承 Thread、实现 Runnable、实现 Callable、使用线程池。
  • 开启线程必须调用start(),直接调用run()只是普通方法执行。
  • 多线程安全根源:原子性、可见性、有序性问题。
  • 解决方案:synchronized、Lock、volatile、ThreadLocal、线程安全集合。
  • 项目开发优先使用线程池,规避频繁创建线程带来的性能隐患。

Spring

Spring 两大核心:IOC(控制反转)、AOP(面向切面编程)

Bean 生命周期: 实例化→填充属性→初始化(afterPropertiesSet、init-method)→使用→销毁 (destroy)

IOC概念:对象创建、依赖交给 Spring 容器管理,不再 new,反转控制权。

AOP概念:横向抽取公共代码(日志、事务、权限),不改动原业务代码增强功能。

五大通知:前置、后置、异常、最终、环绕通知。

动态代理:

  • 目标类实现接口:JDK 动态代理
  • 没实现接口:CGLIB 字节码代理

@Autowired 和 @Resource 区别

  1. @Autowired:Spring 注解,默认按类型注入,配合 @Qualifier 按名称
  2. @Resource:JSR 规范,默认先按名称、再按类型

@Transactional 失效场景

  1. 方法不是 public

@Transactional 基于 AOP 代理,非 public (private/protected) 不会生成代理,事务失效

2.同类中内部调用

原因:this调用不走代理对象,不会切入事务。 解决:从容器拿本类代理对象再调用。

  1. 异常被 try-catch 吃掉,没有抛出异常

  2. 指定了异常,抛出类型不匹配

5.数据库引擎不支持事务

表引擎是 MyISAM(不支持事务),换成 InnoDB。

6.传播行为导致不开启事务

例如:@Transactional(propagation = Propagation.SUPPORTS) 外层无事务,当前方法以非事务运行,出错不回滚。

@Transactional 失效口诀(好记)

私类自捕引擎错,传播配置不生效

逐句释义:

  1. :方法非 public,无法 AOP 代理
  2. :同类 this 内部调用,没走代理
  3. 自捕:异常 try-catch 捕获,未向外抛出
  4. 引擎:数据表 MyISAM 引擎不支持事务
  5. :rollbackFor 指定异常和抛出异常不一致
  6. 传播:传播属性配置不当(SUPPORTS 等无事务运行)

开发规范一句话

统一注解:@Transactional(rollbackFor = Exception.class)

SpringMVC 执行流程

口诀:请映适控视

请求→映射→适配→控制器→视图解析

完整 5 步流程

  1. DispatcherServlet 接收请求(前端控制器,入口)
  2. 处理器映射器 HandlerMapping:根据 URL 找到对应 Controller
  3. 处理器适配器 HandlerAdapter:执行 Controller 方法
  4. Controller:执行业务,返回 ModelAndView
  5. 视图解析器 ViewResolver:解析视图地址,渲染页面返回浏览器

精简面试一句话

请求经过 DispatcherServlet,由映射找控制器、适配器执行,控制器返回数据视图,视图解析后响应页面。

相关推荐
XGeFei1 小时前
【Fastapi学习笔记(3)】——资源的层级关系、安全性-幂等性、Field、工厂函数
笔记·学习·fastapi
星恒随风3 小时前
Python 基础语法详解(一):从表达式、变量到数据类型
开发语言·笔记·python·学习
tedcloud1234 小时前
cc-switch评测:多AI Coding Agent管理工具详解
数据库·人工智能·sql·学习·自动化
胡图图不糊涂^_^5 小时前
测试BUG篇
学习·bug·测试
humors2217 小时前
学习方法的系统梳理与实践应用
学习·学习方法
爱讲故事的7 小时前
操作系统第一讲复习:为什么学习操作系统,以及操作系统到底在做什么?
linux·开发语言·windows·学习·ubuntu·c#
胡图图不糊涂^_^9 小时前
测试用例篇——设计测试用例的方法
笔记·学习·测试用例·判定表法·正交法生成用例测试·等价类·边界值
Fanfanaas9 小时前
C++ 继承
java·开发语言·jvm·c++·学习·算法
飞翔中文网10 小时前
Java学习笔记之抽象类
java·笔记·学习