《Java 高级编程》2.1 反射核心:Class、Method 与访问控制
libraryd 的审计日志不想为 Book、Member、Loan 各写一套字段提取代码,反射是把它做成一个通用组件的最小代价。本节从 Class 的三种来源讲到 Method 查找、invoke 调用、构造器创建,再落到 trySetAccessible 与模块边界,最后给出可用于 record 的字段映射实现。
tag
libraryd 的审计日志不想为 Book、Member、Loan 各写一套字段提取代码,反射是把它做成一个通用组件的最小代价。本节从 Class 的三种来源讲到 Method 查找、invoke 调用、构造器创建,再落到 trySetAccessible 与模块边界,最后给出可用于 record 的字段映射实现。
libraryd 的 JSON 层要反序列化 Page<Book>,但 Page.class 只保留原始类型,Book 这个实参在运行时已经消失。本节用真实编译错误说明擦除的边界,实现一个基于匿名子类的 TypeRef,并把 Page<Book>、Map<String, List<Book>> 的类型令牌接到接口响应解码上。
libraryd 的查询 API 一旦同时接受 Book 和子类型、又要往集合里写回结果,就会撞上泛型不变性。本节用数组协变与 ArrayStoreException 做对照,按 PECS 拆解 extends 与 super 的读写方向,并把 Page 映射、批量保存和过滤谓词的签名落到仓储端口上。
libraryd 的仓储接口从每个实体一份复制粘贴,收敛到 Repository<T, ID>。本节解释两个类型参数各自约束什么、有界类型参数如何把可比较性写进签名、编译器生成的桥方法从哪来,并用 javap 看清擦除后的真实字节码,最后给出泛型仓储的边界清单。
《Java 高级编程》全书导航页:说明卷三在四卷本中的位置、读者画像与前置知识,给出机制补课、改造 libraryd 与排障速查三条学习路径,并按四个部分列出 9 章 27 节的完整索引、项目改造状态、版本依赖与验证方式,另附序、前言和附录 A–D。
交代本书的读者对象、前置知识与九章结构,列出 JDK 25、Maven、Docker 与 clang 的环境清单和真实版本输出,说明代码、实验与命令的书写约定、三种验证层次,以及版本不一致时从 JDK、预览开关、模块路径到本地库的六步排查顺序。
说明卷三为什么在能跑的服务之后还要单独讲语言机制,交代类型系统、运行时、并发与平台性能四个层次,与卷四 JVM 调优和 Spring Boot 卷的分工,并列出 JDK 25 中 synchronized 不再 pin 虚拟线程、ScopedValue 正式、StructuredTaskScope 仍是预览等版本边界,以及三条阅读路径与代码验证方式。
把 libraryd 的手工装配逐项映射到 Spring Boot 的对应能力:模块与依赖、数据访问、事务、Web 路由、参数校验、错误契约、日志、指标、缓存、测试与打包,并给出从本书代码迁移到 Spring Boot 的顺序与最容易踩错的五个差异点。
按「构建、数据库、迁移、连接池、事务、HTTP、容器」七个层次组织 libraryd 的常见故障:给出真实报错原文、触发条件、定位命令与修复方式,并说明排查时为什么应先确认失败发生在哪一层,而不是先改配置。附录末尾附一页式诊断命令清单,便于按层逐项核对。
把 libraryd 用到的 JDBC 驱动、连接池、迁移工具、HTTP 框架、JSON、校验、日志、指标、追踪、缓存与测试库放在一起对比,说明每个选择的约束、替代方案与不适用场景,并给出一张可复用的选型表、四个常见误判与替换前的检查清单。
给出一套可直接对照的 libraryd 多模块 Maven 配置:父 POM 的属性与 dependencyManagement、五个子模块的依赖声明、编译与测试插件、Enforcer、JaCoCo、Checkstyle、SpotBugs、Shade、Jib 的完整片段,以及 quality、integration 两个 profile 与常用诊断命令。
《Java 编程实战》全书导航页:说明从卷一 CLI 到 libraryd 服务的升级路线、读者画像与前置知识,给出六周实战路径与四类读者的入口建议,并按六个部分列出 16 章 48 节的完整索引,另附序、前言、附录 A–D,每节配一句话定位与项目状态说明。
交代本书的读者对象、前置知识与六部分结构,列出 JDK 25、Maven、Docker 与 PostgreSQL 17 的环境清单和真实版本输出,说明代码、输出、容器与命令的书写约定,以及三种阅读路径、验证代码的四个层次与版本不一致时的排查顺序。
说明卷二为什么在卷一之后单独成书、为什么不用 Spring 而是手工搭出 libraryd 的每个基础设施位置,交代从 CLI 到可部署服务的六道工程门槛、与 Spring Boot 卷和本站 Java 专题的分工,以及本书刻意不写的 JVM 机制、GC 调优与验证方式。
镜像能启动不等于能安全发布。本节用 libraryd 的真实启动失败、Flyway checksum 冲突和 /health 503 输出,讲清环境变量配置、只前进的迁移、扩展-收缩改造,以及灰度发布、回滚判据和连接池容量的具体计算方法等。
fat jar 解决了依赖问题,但目标机器仍然需要 JRE、正确的用户和健康检查。本节用多阶段 Dockerfile 把 libraryd 装进非 root 镜像,再用 Jib 3.5.2 在不依赖 Docker daemon 的情况下构建,并给出 352 MB 镜像的真实运行结果。
mvn package 默认只产出几十 KB 的瘦 jar,离开 Maven 就找不到依赖。本节用 Shade 3.6.2 生成可执行的 libraryd fat jar,处理 SPI 与签名文件,再用 jdeps 和 jlink 裁出 53 MB 运行时,并给出真实的 jar 大小与启动耗时。
单元、持久化和 Web 测试都绿,并不代表 libraryd 能启动。本节用随机端口启动完整 LibraryApplication,走一遍借阅、续借、归还、健康检查和指标,并把 mvn verify 接进 GitHub Actions,给出 33 个测试的真实耗时。
手工 docker run 的数据库会随开发机和 CI 漂移,H2 又撑不起 libraryd 的部分索引和 pg_trgm。本节用 Testcontainers 1.21.4 启动 postgres:17-alpine,讲清静态容器、连接注入、Flyway 迁移、容器复用与清理的真实行为。
libraryd 有 33 个测试,但把领域、仓储、HTTP 和端到端混在一起跑,会让失败定位和反馈速度一起变差。本节按模块划出四层测试,说明每层该依赖什么、不该依赖什么,并用真实的测试数量、耗时与配比解释为什么端到端只保留两个主链路用例。