
1. 这不是“又一篇框架推荐文”为什么2026年还在谈Spring Boot且它依然不可替代你点开这篇文章大概率不是因为想听“Spring Boot很火”这种废话——毕竟连刚学完Java基础语法的实习生都能在GitHub上fork一个starter项目跑起来。真正值得问的是当Quarkus喊着“亚毫秒启动”Micronaut强调“编译期AOP”GraalVM把JVM生态往原生镜像方向猛推的今天为什么一家中型电商公司的技术选型会上CTO拍板说“新业务线继续用Spring Boot 3.3”而不是“试试更时髦的”答案不在PPT里而在每天凌晨三点告警群弹出的那条java.lang.OutOfMemoryError: Metaspace日志背后在运维同事反复确认“这个新服务的健康检查端点是不是真能反映DB连接池状态”的追问里在应届生入职第一周就独立修复了一个Transactional失效导致的数据不一致Bug的实操现场里。Spring Boot不是最炫的技术但它是最经得起时间压测、团队轮换、业务突变和故障夜袭的Java工程化底盘。它解决的从来不是“能不能写出来”的问题而是“能不能稳稳扛住、清清楚楚知道哪里扛不住、以及扛不住时怎么快速切掉”的问题。关键词——工程成熟度、生态确定性、团队认知成本、故障可追溯性——这四个词才是2026年你决定是否投入时间深挖Spring Boot的核心标尺。它适合谁不是只适合想进大厂刷面试题的人而是适合所有要真实交付、持续维护、需要和DBA、前端、测试、运维甚至产品经理对齐接口语义的开发者。你不需要把它当成“终极答案”但必须把它当作理解Java企业级开发逻辑的“通用语言母本”。2. 内容整体设计与思路拆解为什么是“Best”而不是“Most Popular”2.1 “Best”的底层逻辑不是性能竞赛而是风险对冲很多人误以为“Best”等于“最快”或“最轻”。这是典型的技术浪漫主义陷阱。我们来算一笔硬账一个标准Spring Boot 3.3 Web应用含Spring Data JPA、Spring Security、Actuator启动耗时约1.8秒JDK 21 GraalVM Native Image预编译后可压到320ms而Quarkus同功能应用启动约85ms。差距明显。但关键问题是你的业务系统有多少时间花在“启动”上一个运行7×24小时的订单服务全年启动次数可能不超过5次发布、回滚、灾备切换。而它每秒要处理300笔支付请求其中92%的耗时瓶颈在数据库连接池等待、Redis缓存穿透、第三方支付网关超时重试上。这时候框架启动快1秒对SLA服务等级协议的影响趋近于零但Spring Boot的DataSourceHealthIndicator能否在连接池耗尽前15秒发出精准告警Retryable注解能否在调用支付宝接口失败时自动执行指数退避重试spring-boot-starter-validation能否在Controller层就拦截掉99.7%的非法参数从而避免后续层层透传——这些才是决定你KPI是拿奖金还是写复盘报告的关键。Spring Boot的“Best”本质是将80%的共性工程难题配置管理、健康检查、指标暴露、外部化配置、环境隔离封装成开箱即用的约定把开发者心智资源从“造轮子”强制释放到“解决业务域问题”上。它不承诺性能天花板但承诺了问题定位的下限高度——当你看到/actuator/metrics/jvm.memory.used指标异常飙升你知道问题一定在堆内存分配或GC策略当你看到/actuator/health/db返回DOWN你知道一定是数据源配置或网络链路出了问题。这种确定性在分布式系统复杂度指数级增长的2026年比任何微秒级的启动优化都珍贵。2.2 方案选型背后的残酷现实团队能力光谱与技术债容忍度假设你是一家有200名开发者的金融科技公司核心交易系统已稳定运行8年技术栈是Spring Boot 2.7 JDK 11。现在要启动一个面向C端用户的营销活动平台。你会选什么选项ASpring Boot 3.3 JDK 21 Spring Authorization ServerOAuth2.1选项BQuarkus 3.12 Panache RESTEasy Reactive选项C纯Vert.x 4.5 自研配置中心选B或C的团队通常具备三个前提1有专职的平台工程Platform Engineering团队负责统一构建、部署、监控基座2所有后端工程师对Reactive编程模型、Netty线程模型、编译期代理原理有深度理解3能接受初期因生态不成熟导致的调试工具缺失比如Quarkus Dev UI对某些自定义Filter的断点支持不完善。而现实中90%的团队不具备这些条件。他们的真实情况是团队里有5年经验的资深工程师也有刚毕业3个月、还在熟悉Git分支策略的新人运维同学的监控脚本是基于Spring Boot Actuator的Prometheus Exporter写的换框架意味着重写所有告警规则测试同学的自动化用例是用SpringBootTestTestRestTemplate写的迁移成本远超业务代码本身。Spring Boot的“Best”恰恰体现在它对团队能力光谱的包容性上。一个RestController的写法从Spring Boot 1.0到3.3几乎没变application.yml的配置结构和十年前的application.properties逻辑完全一致。这种向后兼容的“惰性”不是技术停滞而是对人类协作成本的敬畏。它允许你在不颠覆整个工程体系的前提下渐进式升级先升JDK再升Spring Boot主版本最后替换掉过时的Starter。这种可控的演进路径让技术决策从“豪赌”回归到“精算”。2026年当AI辅助编码工具已能自动生成CRUD代码时真正的护城河早已从“会不会写代码”转移到“能不能在复杂约束下做出可持续的工程决策”。2.3 避开的坑那些被过度宣传却极少落地的“银弹”必须戳破几个2026年依然在传播的迷思“Spring Boot太重微服务必须用轻量框架”错。微服务的“轻”指服务粒度小、职责单一、部署独立而非单个JAR包体积。一个Spring Boot应用打成Fat Jar也就25MB而Docker镜像层缓存后实际网络传输增量常低于2MB。真正“重”的是业务逻辑本身——比如一个风控引擎服务无论用什么框架它都要加载GB级的规则模型、连接多个下游数据源、执行复杂的实时计算。框架的“体重”在此类场景下可忽略不计。“响应式编程是未来Spring WebFlux必须上”错。WebFlux的真正价值场景非常明确1高并发、低计算、I/O密集型服务如API网关、实时消息推送2需要与Reactive数据库如R2DBC深度集成。但绝大多数业务系统订单、支付、用户中心是CPU密集型关系型数据库主导此时阻塞式编程模型Spring MVC的线程模型更直观、调试更简单、生态更成熟。强行上WebFlux只会让Mono.just()和flatMap()把业务逻辑变成俄罗斯套娃增加3倍以上的排查难度。“Spring Cloud Alibaba已死必须迁移到Service Mesh”错。Service Mesh如Istio解决的是跨语言、跨框架的服务治理问题。而一个纯Java技术栈、内部服务间调用99%走Feign/Ribbon的团队用Spring Cloud的LoadBalanced RestTemplate配合Nacos其稳定性、可观测性、运维成本远优于在每个Pod里塞一个Sidecar。Mesh的价值在于当你有Go写的风控服务、Python写的AI模型服务、Node.js写的前端BFF需要统一做熔断、限流、链路追踪时才真正显现。对单一语言生态它往往是“杀鸡用牛刀”。Spring Boot的“Best”正在于它清醒地知道自己该在哪条战线上发力——不做全栈革命者只做企业级开发的“稳定器”和“翻译官”。它把JVM的复杂性、HTTP协议的细节、数据库连接的坑、安全认证的繁琐翻译成Java开发者熟悉的Bean、Value、PreAuthorize。这种“翻译”的质量经过15年、数百万项目的实战淬炼已达到极高的信噪比。3. 核心细节解析与实操要点从“能跑”到“跑得明白”的关键跃迁3.1 Starter机制的本质不是魔法是契约化的依赖装配很多初学者觉得spring-boot-starter-web是个黑盒。其实它就是一个Maven BOMBill of Materials 自动配置类AutoConfiguration的组合体。以spring-boot-starter-data-jpa为例它的核心文件是spring.factoriesSpring Boot 2.7后迁移到META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsorg.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration这行配置的意思是“当classpath下存在HibernateJpaAutoConfiguration所需的类如LocalContainerEntityManagerFactoryBean且用户未手动定义同类型Bean时Spring Boot就自动加载这个配置类”。而HibernateJpaAutoConfiguration内部会根据application.yml中的spring.jpa.*属性自动创建DataSource、EntityManagerFactory、TransactionManager等Bean并设置好HikariCP连接池参数、Hibernate方言、DDL生成策略。关键实操要点不要盲目禁用AutoConfigSpringBootApplication(exclude {DataSourceAutoConfiguration.class})看似能“精简”实则破坏了Starter的契约。你禁用了DataSourceAutoConfiguration就得自己手写Bean创建DataSource并确保其Primary、ConfigurationProperties(spring.datasource)等注解正确否则JdbcTemplate注入会失败。理解ConditionalOn*系列注解这是Spring Boot自动配置的基石。ConditionalOnClass(DataSource.class)表示只有classpath存在DataSource类时才生效ConditionalOnMissingBean(DataSource.class)表示当容器中没有DataSource类型的Bean时才创建。这两个注解组合保证了“用户自定义优先”原则——你只要自己定义一个DataSourceBeanSpring Boot就绝不会覆盖它。调试自动配置启动时加JVM参数--debug控制台会输出详细的CONDITIONS EVALUATION REPORT告诉你哪些AutoConfig被加载、哪些被跳过、原因是什么如ConditionalOnClass未满足。这是排查“为什么我的配置不生效”的第一手资料。提示Starter不是越少越好。一个健康的Spring Boot应用通常包含spring-boot-starter-web、spring-boot-starter-data-jpa、spring-boot-starter-validation、spring-boot-starter-actuator、spring-boot-starter-log4j2替代默认Logback便于日志审计这5个核心Starter。额外添加spring-boot-starter-cache或spring-boot-starter-amqp应严格对应业务需求而非“听说有用”。3.2 外部化配置的层级战争application.yml不是终点而是入口Spring Boot的配置优先级从高到低是命令行参数--server.port8081java:comp/envJNDI属性Java系统属性System.getProperties()操作系统环境变量RandomValuePropertySourcerandom.*jar包外的application-{profile}.properties/yml如config/application-prod.ymljar包内的application-{profile}.properties/ymljar包外的application.properties/ymljar包内的application.properties/yml这个顺序不是理论而是每天都在发生的“配置覆盖战”。举个真实案例某次生产发布运维同学在启动脚本里写了-Dspring.profiles.activeprod但开发同学在application-prod.yml里配了spring.redis.hostredis-prod.internal而环境变量里又设置了SPRING_REDIS_HOSTredis-staging.internal。结果服务连到了测试环境的Redis导致缓存雪崩。关键实操要点永远用application-{profile}.yml不用application.ymlapplication.yml是全局默认极易被意外覆盖。所有环境特定配置必须放在application-dev.yml、application-test.yml、application-prod.yml中并通过spring.profiles.active激活。敏感配置走环境变量或配置中心数据库密码、API密钥等绝不能写在application-prod.yml里。2026年主流做法是K8s Secret挂载为环境变量或接入Apollo/Nacos配置中心通过spring-cloud-starter-alibaba-nacos-config动态拉取。用ConfigurationProperties绑定类型安全配置不要用Value(${xxx})硬编码字符串。定义一个POJOComponent ConfigurationProperties(prefix app.payment) Validated public class PaymentConfig { NotBlank private String alipayAppId; Min(1000) private int timeoutMs; // getter/setter }这样timeoutMs会被自动转为int且Min校验会在启动时触发避免运行时NumberFormatException。注意ConfigurationProperties类必须有无参构造器且setter方法不能是private。这是Spring Boot 3.x的强约束违反会导致BindingValidationException。3.3 Actuator的深度挖掘从“健康检查”到“系统透视镜”/actuator/health只是冰山一角。2026年一个合格的Spring Boot工程师必须掌握以下端点/actuator/metrics获取所有埋点指标。curl http://localhost:8080/actuator/metrics | jq .names[]可列出所有指标名如jvm.memory.used、http.server.requests、datasource.hikaricp.connections.active。/actuator/metrics/http.server.requests?tagstatus:500taguri:/api/order按标签过滤精准定位错误接口。/actuator/threaddump获取JVM线程快照分析死锁、线程阻塞。jstack -l pid的Web版。/actuator/heapdump生成heap.hprof文件用VisualVM或Eclipse MAT分析内存泄漏。/actuator/loggers动态调整日志级别。POST /actuator/loggers/com.example.service.OrderService{configuredLevel: DEBUG}无需重启即可开启DEBUG日志排查线上疑难问题。关键实操要点生产环境必须关闭敏感端点/actuator/env会暴露所有环境变量含密码/actuator/beans会暴露所有Spring Bean定义。在application-prod.yml中management: endpoints: web: exposure: include: health,metrics,threaddump,loggers # exclude: env,beans,conditions # 显式排除 endpoint: health: show-details: when_authorized # 仅授权用户可见详情集成Prometheus添加micrometer-registry-prometheus依赖/actuator/prometheus端点会输出Prometheus格式指标。Grafana看板可直接对接实现“指标-日志-链路”三位一体监控。自定义健康指示器当/actuator/health返回UP但业务上“订单服务不可用”如依赖的风控API超时需自定义Component public class RiskApiHealthIndicator implements HealthIndicator { Override public Health health() { try { // 调用风控API的健康检查接口 restTemplate.getForObject(http://risk-api/health, String.class); return Health.up().withDetail(responseTime, 23ms).build(); } catch (Exception e) { return Health.down().withDetail(error, e.getMessage()).build(); } } }这样K8s的Liveness Probe就能感知到业务级故障自动重启Pod。4. 实操过程与核心环节实现一个可落地的“高可用订单服务”骨架4.1 项目初始化与依赖选型拒绝“全家桶”拥抱“最小必要”使用 Spring Initializr 2026年已支持Spring Boot 3.3勾选Spring Web替代旧版spring-boot-starter-webSpring Data JPAORM层搭配H2用于本地开发PostgreSQL用于生产Spring Boot DevTools开发期热部署CtrlF9刷新类LombokData、Builder减少样板代码ValidationNotBlank、Min等校验Actuator生产监控Spring Boot Configuration Processor为ConfigurationProperties生成元数据IDE自动提示不勾选Spring Security订单服务本身不处理登录由统一网关鉴权、Thymeleaf纯API服务、Spring Cloud Netflix已淘汰改用Spring Cloud Alibaba或K8s Service Discovery。生成后pom.xml核心依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependency !-- 生产数据库驱动 -- dependency groupIdorg.postgresql/groupId artifactIdpostgresql/artifactId scoperuntime/scope /dependency !-- 本地开发用H2 -- dependency groupIdcom.h2database/groupId artifactIdh2/artifactId scoperuntime/scope /dependency4.2 核心业务代码从Controller到Repository的“防御式编程”订单实体Order.javaEntity Table(name t_order) Data Builder NoArgsConstructor AllArgsConstructor public class Order { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; Column(name order_no, unique true, nullable false) NotBlank(message 订单号不能为空) Size(max 64, message 订单号长度不能超过64位) private String orderNo; Column(name user_id, nullable false) NotNull(message 用户ID不能为空) private Long userId; Column(name amount, nullable false, precision 12, scale 2) DecimalMin(value 0.01, message 订单金额不能小于0.01) private BigDecimal amount; Column(name status, nullable false) Enumerated(EnumType.STRING) NotNull(message 订单状态不能为空) private OrderStatus status; // 枚举CREATED, PAID, SHIPPED, COMPLETED, CANCELLED Column(name created_at, nullable false, updatable false) CreationTimestamp private LocalDateTime createdAt; Column(name updated_at, nullable false) UpdateTimestamp private LocalDateTime updatedAt; }Controller层OrderController.javaRestController RequestMapping(/api/orders) Validated public class OrderController { private final OrderService orderService; public OrderController(OrderService orderService) { this.orderService orderService; } PostMapping public ResponseEntityOrderResponse createOrder(Valid RequestBody CreateOrderRequest request) { // 1. 参数校验已由Valid完成此处只做业务校验 if (request.getAmount().compareTo(BigDecimal.ZERO) 0) { return ResponseEntity.badRequest() .body(OrderResponse.error(订单金额必须大于0)); } // 2. 调用服务层捕获业务异常 try { Order order orderService.createOrder(request); return ResponseEntity.ok(OrderResponse.success(order)); } catch (InsufficientBalanceException e) { // 余额不足等业务异常返回400 return ResponseEntity.badRequest() .body(OrderResponse.error(余额不足 e.getMessage())); } catch (Exception e) { // 未预期异常记录ERROR日志返回500 log.error(创建订单失败request{}, request, e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(OrderResponse.error(系统繁忙请稍后重试)); } } }Service层OrderService.javaService Transactional public class OrderService { private final OrderRepository orderRepository; private final UserService userService; // 依赖用户服务查余额 private final PaymentService paymentService; // 依赖支付服务 public OrderService(OrderRepository orderRepository, UserService userService, PaymentService paymentService) { this.orderRepository orderRepository; this.userService userService; this.paymentService paymentService; } Transactional(rollbackFor Exception.class) public Order createOrder(CreateOrderRequest request) { // 1. 检查用户余额调用远程服务 User user userService.getUserById(request.getUserId()); if (user.getBalance().compareTo(request.getAmount()) 0) { throw new InsufficientBalanceException(余额不足); } // 2. 创建订单本地事务 Order order Order.builder() .orderNo(generateOrderNo()) .userId(request.getUserId()) .amount(request.getAmount()) .status(OrderStatus.CREATED) .build(); order orderRepository.save(order); // 3. 扣减余额远程调用需幂等 userService.deductBalance(request.getUserId(), request.getAmount()); // 4. 发起支付异步避免阻塞 paymentService.asyncPay(order.getId(), request.getAmount()); return order; } private String generateOrderNo() { return ORD System.currentTimeMillis() ThreadLocalRandom.current().nextInt(1000, 9999); } }Repository层OrderRepository.javaRepository public interface OrderRepository extends JpaRepositoryOrder, Long { // Spring Data JPA自动生成SQL OptionalOrder findByOrderNo(String orderNo); // 自定义查询用JPQL Query(SELECT o FROM Order o WHERE o.userId :userId AND o.status IN :statuses ORDER BY o.createdAt DESC) ListOrder findOrdersByUserIdAndStatuses(Param(userId) Long userId, Param(statuses) ListOrderStatus statuses); // 原生SQL用于复杂统计 Query(value SELECT COUNT(*) FROM t_order WHERE status PAID AND created_at :startDate, nativeQuery true) long countPaidOrdersSince(Param(startDate) LocalDateTime startDate); }4.3 生产就绪配置application-prod.yml的黄金参数# 服务器配置 server: port: 8080 tomcat: max-connections: 5000 accept-count: 1000 max-threads: 200 min-spare-threads: 50 # 数据库配置生产环境走Nacos spring: datasource: url: jdbc:postgresql://pg-prod:5432/order_db?currentSchemapublic username: ${DB_USERNAME:default_user} password: ${DB_PASSWORD:default_pass} hikari: maximum-pool-size: 50 minimum-idle: 10 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000 validation-timeout: 3000 leak-detection-threshold: 60000 # 检测连接泄漏毫秒 jpa: hibernate: ddl-auto: validate # 生产环境严禁update/createvalidate只校验表结构 show-sql: false properties: hibernate: format_sql: false jdbc: batch_size: 20 fetch_size: 50 cache: use_second_level_cache: true use_query_cache: false # Actuator安全配置 management: endpoints: web: exposure: include: health,metrics,threaddump,loggers,prometheus base-path: /actuator endpoint: health: show-details: when_authorized metrics: export: prometheus: enabled: true # 日志配置 logging: level: root: INFO com.example.order: DEBUG pattern: console: %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n file: name: logs/order-service.log max-size: 100MB max-history: 304.4 Docker化与K8s部署从本地到云原生的平滑过渡Dockerfile基于JDK 21 SlimFROM openjdk:21-jdk-slim VOLUME /tmp ARG JAR_FILEtarget/order-service-1.0.0.jar COPY ${JAR_FILE} app.jar ENTRYPOINT [java,-Djava.security.egdfile:/dev/./urandom,-jar,/app.jar]K8s Deployment YAML关键字段apiVersion: apps/v1 kind: Deployment metadata: name: order-service spec: replicas: 3 selector: matchLabels: app: order-service template: metadata: labels: app: order-service spec: containers: - name: order-service image: harbor.example.com/order-service:1.0.0 ports: - containerPort: 8080 livenessProbe: # 存活探针 httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 60 periodSeconds: 30 readinessProbe: # 就绪探针 httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 30 periodSeconds: 10 resources: requests: memory: 512Mi cpu: 250m limits: memory: 1Gi cpu: 500m env: - name: SPRING_PROFILES_ACTIVE value: prod - name: DB_USERNAME valueFrom: secretKeyRef: name: db-secret key: username - name: DB_PASSWORD valueFrom: secretKeyRef: name: db-secret key: password关键说明livenessProbe用/actuator/health/liveness当服务卡死如GC停顿时K8s会杀死Pod重建readinessProbe用/actuator/health/readiness当数据库连接池耗尽时该端点返回DOWNK8s会将Pod从Service Endpoints中移除避免流量打入resources.limits设为1Gi内存是为了防止OOM Killer无差别杀进程requests设为512Mi是K8s调度器分配节点的依据环境变量从Secret读取确保密码不泄露。5. 常见问题与排查技巧实录那些文档里不会写的“血泪教训”5.1 启动失败NoSuchMethodError与ClassNotFoundException的真相现象Spring Boot 3.3应用启动报错java.lang.NoSuchMethodError: void org.springframework.boot.context.config.ConfigDataLocationResolver.resolve(...)根因混合了不同版本的Spring Boot依赖。例如你显式引入了spring-boot-starter-web:2.7.18而父POM声明了spring-boot-dependencies:3.3.0。Maven的依赖调解Dependency Mediation会保留2.7.18的jar但3.3.0的spring-boot核心模块期望调用3.3.0版本的ConfigDataLocationResolver而2.7.18里根本没有这个方法。排查步骤mvn dependency:tree -Dincludesorg.springframework.boot查看所有Spring Boot相关依赖的版本找到版本不一致的项如spring-boot-starter-web:2.7.18在pom.xml中用exclusions排除冲突依赖或统一升级到3.3.x。实操心得永远用spring-boot-starter-parent作为parent不要手动管理Spring Boot依赖版本。如果必须用其他parent如公司统一parent则在properties中强制指定spring-boot.version3.3.0/spring-boot.version。5.2 性能瓶颈HikariCP连接池“假死”之谜现象应用运行正常但突然大量请求超时/actuator/metrics/datasource.hikaricp.connections.active指标显示连接数长期为0而/actuator/metrics/datasource.hikaricp.connections.idle也接近0。根因HikariCP的connection-timeout默认30秒与数据库TCP连接超时如PostgreSQL的tcp_keepalives_idle7200不匹配。当数据库因网络抖动主动断开空闲连接HikariCP的validation-timeout默认5秒检测到连接失效但connection-timeout太长导致新请求在连接池中排队等待直到超时。解决方案spring: datasource: hikari: connection-timeout: 10000 # 缩短至10秒 validation-timeout: 3000 # 缩短至3秒 idle-timeout: 600000 # 10分钟空闲后回收 max-lifetime: 1800000 # 30分钟最大生命周期强制刷新实操心得在K8s环境中务必设置max-lifetime。因为K8s Service的ClusterIP可能在Pod重建后变化旧连接会指向已销毁的Pod IP导致“幽灵连接”。max-lifetime强制连接在30分钟内重建规避此问题。5.3 事务失效Transactional不生效的7种死法场景原因修复方案私有方法调用Transactional方法被同一类的私有方法调用Spring AOP代理无法拦截改为public或注入自身this不推荐或用TransactionTemplate非public方法Transactional只能作用于public方法改为public自调用this.method()同一Bean内this.createOrder()绕过代理改为注入自身Autowired private OrderService self; self.createOrder()或用ApplicationContext.getBean()异常被吞try-catch捕获了异常但未抛出事务不会回滚catch中throw new RuntimeException(e)或配置Transactional(rollbackFor Exception.class)检查异常未配置默认只对RuntimeException回滚IOException等检查异常需显式声明Transactional(rollbackFor Exception.class)传播行为错误REQUIRES_NEW在嵌套调用中创建新事务但外层事务失败不影响内层根据业务语义选择REQUIRED默认或REQUIRES_NEW异步方法Async方法在新线程执行脱离原事务上下文用TransactionTemplate手动管理或改用消息队列最终一致性5.4 Actuator端点404/actuator/health不存在现象启动成功但访问http://localhost:8080/actuator/health返回404。根因Spring Boot 2.0默认只暴露/actuator/health和/actuator/info两个端点。其他端点需显式配置。修复在application.yml中management: endpoints: web: exposure: include: * # 或显式列出health,info,metrics,threaddump注意include: *在生产环境是危险操作必须配合Spring Security限制访问权限。5.5 日志乱码Linux服务器上中文日志显示为???