JAVA · Spring / JVM 生态
Java 生态速查
梳理 Spring Boot 高频核心注解与 JVM 生产环境常用参数:从依赖注入、声明式事务到堆内存分配与 GC 调优,写代码、调优时随查随用。
6速查小节
12Spring 注解
13JVM 参数
7Lombok 注解
8工程配置
5Actuator 端点
📖 速查表
点击展开各小节
🍃 Spring Boot 核心注解
| 注解 | 作用 | 说明 / 常用属性 |
|---|---|---|
| @RestController | 组合 @Controller + @ResponseBody,所有方法返回 JSON | 标记 RESTful API 控制器,返回值自动序列化为 JSON |
| @RequestMapping | 映射 HTTP 请求到处理器方法 | value 路径,method 请求方式,params 参数过滤,headers 请求头过滤 |
| @Autowired | 自动装配 Spring Bean | 按类型注入,可配合 @Qualifier 指定 Bean 名称 |
| @Service | 标记服务层组件 | 业务逻辑层,@Component 的语义化别名 |
| @Repository | 标记数据访问层组件 | DAO 层,支持持久层异常转换(DataAccessException) |
| @Configuration | 标记配置类,包含一个或多个 @Bean 方法 | 替代 XML 配置,由 Spring 容器处理 |
| @Bean | 声明一个由 Spring 容器管理的 Bean | 在 @Configuration 类的方法上使用,name 指定 Bean 名称 |
| @Value | 注入配置属性值 | @Value("${app.name}") 从配置文件读取,支持 SpEL 表达式 |
| @Transactional | 声明式事务管理 | readOnly 只读优化,rollbackFor 指定回滚异常,propagation 传播行为 |
| @Cacheable | 方法结果缓存 | value 缓存名称,key 缓存键,unless 条件过滤不缓存 |
| @Async | 异步执行方法 | 方法在独立的线程池中异步执行,需启用 @EnableAsync;同类自调用同样失效 易错 |
| @Scheduled | 定时任务 | cron 表达式,fixedDelay 固定延迟,fixedRate 固定速率 |
⚙️ JVM 常用参数
| 参数 | 说明 | 示例 / 建议值 |
|---|---|---|
| -Xms | 初始堆大小(JVM 启动时分配的堆内存) | -Xms512m / -Xms4g |
| -Xmx | 最大堆大小(JVM 允许的最大堆内存) | -Xmx2g / -Xmx8g |
| -Xmn | 新生代大小(影响 Minor GC 频率) | -Xmn512m(通常为堆的 1/3~1/4) |
| -XX:+UseG1GC | 使用 G1 垃圾回收器(JDK 9+ 默认) | 适用于大堆内存(>4G),低延迟场景 |
| -XX:MaxGCPauseMillis | G1 GC 最大停顿时间目标(毫秒) | -XX:MaxGCPauseMillis=200 |
| -XX:+UseConcMarkSweepGC | 使用 CMS 垃圾回收器(JDK 9 弃用,JDK 14 移除) | 低停顿,但存在碎片化和 CPU 高问题 |
| -XX:+UseParallelGC | 使用并行垃圾回收器(JDK 8 默认) | 高吞吐量,适合批处理、科学计算 |
| -XX:MetaspaceSize | 元空间初始大小(取代 JDK 8 之前的永久代) | -XX:MetaspaceSize=256m |
| -XX:MaxMetaspaceSize | 元空间最大大小 | -XX:MaxMetaspaceSize=512m |
| -Xss | 每个线程的栈大小 | -Xss256k(减小栈空间可容纳更多线程) |
| -XX:+HeapDumpOnOutOfMemoryError | OOM 时自动生成 Heap Dump | -XX:HeapDumpPath=/tmp/dump.hprof |
| -XX:+PrintGCDetails | 打印详细 GC 日志 | -Xlog:gc*(JDK 9+ 新语法) |
| -D | 设置系统属性 | -Dserver.port=8080 -Dspring.profiles.active=prod |
🥾 Lombok 常用注解
| 注解 | 作用 | 说明 / 注意 |
|---|---|---|
| @Data | 一步生成 getter/setter/toString/equals/hashCode | 组合注解;JPA 实体慎用,equals/hashCode 涉及关联字段易出问题 注意 |
| @Getter | 为字段生成 getter 方法 | 可标注在类或字段上;@Getter(lazy = true) 支持惰性初始化 |
| @Setter | 为字段生成 setter 方法 | AccessLevel.NONE 可对个别字段跳过生成,敏感字段控制写入入口 |
| @Builder | 生成链式 Builder,多字段对象构造更清晰 | 字段默认值需配 @Builder.Default,否则构造时为 0 或 null |
| @Slf4j | 生成 private static final Logger log 字段 | 直接 log.info() 使用;Spring Boot 默认搭配 Logback |
| @RequiredArgsConstructor | 为 final / @NonNull 字段生成构造器 | 配合 final 字段实现构造器注入,替代字段级 @Autowired 推荐 |
| @EqualsAndHashCode | 生成 equals 与 hashCode | callSuper = true 时纳入父类字段比较;有继承关系的实体注意一并评估 |
🧾 工程常用配置
| 配置 / 命令 | 说明 | 示例 |
|---|---|---|
| datasource | 数据源与连接池配置 | spring.datasource.url=jdbc:mysql://localhost:3306/db、username / password |
| redis | Redis 连接配置 | spring.redis.host / port / password(Boot 3 为 spring.data.redis.*) |
| mybatis | MyBatis 集成配置 | mybatis.mapper-locations=classpath:mapper/*.xml、map-underscore-to-camel-case=true |
| logging | 日志一行式配置(底层 Logback) | logging.level.root=info、logging.file.name=logs/app.log |
| application-{profile}.yml | 多环境配置文件按环境隔离 | application-dev.yml / application-test.yml / application-prod.yml |
| spring.profiles.active | 指定生效的环境 profile | spring.profiles.active=dev 或启动参数 -Dspring.profiles.active=prod |
| mvn clean package | 清理并打包,产出可执行 Fat Jar | mvn clean package → target/app.jar |
| mvn -DskipTests / -P | 跳过测试、指定 profile 构建(CI 常用组合) | mvn clean package -DskipTests、mvn package -Pprod |
🩺 Actuator 端点
| 端点 | 用途 | 暴露与安全注意 |
|---|---|---|
| /health | 健康检查,供负载均衡 / K8s 探针调用 | 生产建议 show-details=never,避免泄露组件信息 |
| /info | 应用信息:版本、构建时间、描述 | 内容由 info.* 配置提供,不放敏感描述 |
| /metrics | 运行指标:JVM 内存、线程、HTTP 请求等 | 常接入 Prometheus 抓取;对外环境建议关闭或鉴权 |
| /env | 查看环境配置属性与 profile | 默认对敏感值脱敏,仍建议生产仅内网开放 注意 |
| /heapdump | 下载堆转储文件,排查内存泄漏 | 堆快照可能含密钥与用户数据,生产必须禁用或严格鉴权 高危 |
🚨 事务失效场景
「加了 @Transactional 却没回滚」几乎都逃不出这 8 种情况:事务靠代理对象实现,凡是绕过代理或让代理失效的写法都会翻车。排查先问一句——这次调用真的经过代理了吗?
| 失效场景 | 原因 | 正确做法 |
|---|---|---|
| 同类自调用 | this.method() 绕过代理对象,切面增强不生效 最高频 | 拆到另一个 Bean 交叉调用;或注入自身代理,用 AopContext.currentProxy() 调用 |
| 方法非 public | CGLIB / JDK 代理只拦截 public 方法,private、protected 直接跳过事务增强 | 事务方法一律 public;不要把事务标注在接口 default 方法上 |
| 异常被 catch 吞掉 | 方法内 try-catch 后未重新抛出,切面感知不到异常,事务照常提交 | catch 后继续 throw;确需吞异常则手动 setRollbackOnly() |
| 抛受检异常未配 rollbackFor | 默认只回滚 RuntimeException 与 Error,IOException 等受检异常不触发回滚 | @Transactional(rollbackFor = Exception.class) 必配 |
| 传播属性误用 REQUIRES_NEW | 以为「加入外层事务」,实际挂起外层另开独立事务:内层回滚不连带外层,外层回滚也影响不了已提交的内层 | 跟随外层用默认 REQUIRED;局部回滚用 NESTED(保存点实现) |
| 多线程内调用 | 事务上下文绑定 ThreadLocal,子线程不共享连接与事务,异常也传不回主线程 | 事务在主线程统一编排;子线程需要事务时改用编程式事务独立控制 |
| 存储引擎不支持事务 | MySQL 表引擎为 MyISAM,SQL 执行成功但根本没有回滚能力 | SHOW TABLE STATUS 确认引擎为 InnoDB |
| Bean 未被 Spring 管理 | 对象由 new 创建,脱离容器就没有代理,更没有事务 | 交给容器(@Service 等注解)后注入使用 |