Spring Boot Starter 封装实践报告

Spring Boot Starter 封装实践报告:从自动装配原理到手写 Starter 🎯 第 1 步:目标说明 某开发者在日常工作中频繁需要为项目集成日志记录、性能监控、消息通知等功能。每次引入新功能时,都要重复编写相似的配置类、注册 Bean、管理依赖——这些步骤机械而繁琐。Spring Boot Starter 正是为解决这一问题而设计的机制:它把自动配置类与依赖管理打包成一个独立的 Jar 包,引用一个 Starter 依赖就能让某个功能"开箱即用"。 本实践报告的目标如下: 理解 Spring Boot 自动装配(Auto Configuration)的核心原理与执行流程 动手封装一个名为 my-logging-spring-boot-starter 的自定义 Starter,功能是自动记录标注了特定注解的方法的执行耗时 在测试项目中引用自定义 Starter,验证功能正常工作 📌 前置知识:本报告假设读者已经掌握 Java 基础语法、Maven 依赖管理与模块化工程、Spring 的 @Bean 与 @Configuration 注解、Spring Boot 基本使用方式。 📋 第 2 步:前置条件 开始实践前,确保以下软件已正确安装。 软件/依赖 最低版本 说明 JDK 17 Spring Boot 3.2.0 要求 Java 17 及以上 Maven 3.6.3 项目构建、依赖管理与打包 IDE 任意 IntelliJ IDEA(社区版即可)或 VS Code 验证安装: java --version # 期望输出示例:openjdk 17.0.9 2023-10-17 LTS mvn --version # 期望输出示例:Apache Maven 3.9.5 ⚠️ 新手提示:如果 java --version 或 mvn --version 提示"命令未找到",说明对应软件没有安装或没有配置环境变量。JDK 需要设置 JAVA_HOME 并将 %JAVA_HOME%\bin 加入 PATH。Maven 需要将 MAVEN_HOME/bin 加入 PATH。完成配置后重新打开终端再执行验证命令。 ...

十月 14, 2022 · 14 分钟 · 2963 字 · yaomingye

Spring Boot 开发中的上下文

Spring Boot 开发必知:那些高频使用的核心上下文类 🐛 从一个 NPE 说起 同事在 IdUtils 工具类里写了一个生成订单号的方法,需要调用数据库序列服务。代码部署到生产环境后,每隔几天就会抛出一个 NullPointerException,而且总是在凌晨 2 点左右。 排查后发现问题:生成订单号的逻辑需要从 Spring 容器中获取 SequenceService,但 IdUtils 是一个纯静态工具类,不归 Spring 管理。同事的写法是: public class IdUtils { // 这样永远拿不到 Bean——IdUtils 自己都没被 Spring 管理,谁来注入? @Autowired private static SequenceService sequenceService; public static String genOrderId() { return sequenceService.nextVal("order"); // NPE! sequenceService == null } } 这是一个典型场景: 需要在不受 Spring 管理的类中获取 Spring Bean 。解决它的钥匙就是本篇要讲的"上下文类"(Context Classes)——Spring 框架提供的一系列能让你在任何位置获取框架运行时状态的工具。 flowchart LR classDef root fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#bfdbfe,font-weight:bold; classDef branch fill:#2d1a05,stroke:#f59e0b,stroke-width:2px,color:#fde68a,font-weight:bold; classDef leaf fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#e5e7eb; classDef highlight fill:#450a0a,stroke:#dc2626,stroke-width:1.5px,color:#fecaca,font-weight:bold; ROOT[Spring Boot 核心上下文类] ROOT --> B1(1. Web 请求上下文) B1 --> L1["RequestContextHolder\n持有当前请求的 ThreadLocal"] B1 --> L2["ServletRequestAttributes\n封装 HttpServletRequest/Response"] B1 --> L3["RequestContextUtils\nLocale / FlashMap / 输入输出流"] ROOT --> B2(2. Security 安全上下文) B2 --> L4["SecurityContextHolder\n持有当前认证信息的 ThreadLocal"] B2 --> L5["Authentication\nPrincipal / Credentials / Authorities"] ROOT --> B3(3. 事务上下文) B3 --> L6["TransactionSynchronizationManager\n事务状态判断 / 回调注册\n事务资源绑定"] ROOT --> B4(4. 容器上下文) B4 --> L7["ApplicationContext\nSpring 容器本身"] B4 --> L8["ApplicationContextAware\n回调注入容器引用"] B4 --> L9["Environment\n配置属性 / Profile"] ROOT --> B5(5. 其他) B5 --> L10["LocaleContextHolder\n国际化语言上下文"] B5 --> L11["BeanFactory\n底层 IoC 容器"] class ROOT root; class B1,B2,B3,B4,B5 branch; class L1,L2,L3,L4,L5,L6,L7,L8,L9,L10,L11 leaf; class L1,L4,L7 highlight; 🌐 一、Web 请求上下文 ⚙️ 1.1 核心类与底层原理 RequestContextHolder(请求上下文持有者)通过 ThreadLocal(线程局部变量)将当前请求的 ServletRequestAttributes 绑定到当前线程。DispatcherServlet(Spring MVC 的前端控制器)在处理每个请求时,会自动调用 RequestContextHolder.setRequestAttributes() 将请求对象"挂"到当前线程上。 ...

十月 7, 2022 · 12 分钟 · 2418 字 · yaomingye

Spring Boot 日志

Spring Boot 日志:打点位置、框架选型与线上排查全解析 🐛 问题切入:一段没有日志的代码 下面是一个新手开发者写的 Spring Boot 订单服务: @RestController @RequestMapping("/order") public class OrderController { @Autowired private OrderService orderService; @PostMapping("/create") public Result<Order> createOrder(@RequestBody CreateOrderRequest req) { Order order = orderService.createOrder(req); return Result.success(order); } } @Service public class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private InventoryService inventoryService; @Transactional public Order createOrder(CreateOrderRequest req) { // 扣减库存 boolean deducted = inventoryService.deduct(req.getProductId(), req.getQuantity()); if (!deducted) { throw new BusinessException("库存不足"); } // 创建订单 Order order = new Order(); order.setUserId(req.getUserId()); order.setAmount(req.getAmount()); orderMapper.insert(order); return order; } } 某天线上出现了一个问题:用户投诉"我付了钱但订单没创建成功"。后端同学打开服务器,面对空荡荡的日志文件(只有 Spring Boot 默认的启动 banner),完全不知道从哪里下手。 ...

九月 30, 2022 · 13 分钟 · 2638 字 · yaomingye

Servlet 网络编程

🌐 Servlet 网络编程:从 HTTP 协议到 RESTful API、过滤器链、监听器与 Tomcat 部署全解析 1. 问题切入:不用 Spring,如何写一个 HTTP API? 假设你要开发一个用户管理的 RESTful API,要求: 支持 JSON 格式的增删改查 对每个请求打印访问日志 校验请求头中的认证 Token 处理跨域请求 如果使用 Spring Boot,一个 @RestController 就解决了。但 Spring MVC 的底层是什么?DispatcherServlet、FilterChain、HandlerInterceptor 这些概念是怎么来的? 这篇博客将用纯 Servlet 实现上述所有需求,让你理解 Spring MVC 底层的每一块砖。 在开始之前,先看最终效果 —— 一个纯 Servlet 实现的用户 API: // GET /api/users → 查询所有用户(JSON) // GET /api/users/1 → 查询单个用户(JSON) // POST /api/users → 创建用户(JSON请求体) // PUT /api/users/1 → 更新用户(JSON请求体) // DELETE /api/users/1 → 删除用户 2. Servlet 是什么 Servlet(Server Applet,服务端小程序)是 Java EE 规范中定义的一套 服务器端 HTTP 处理接口。它不是独立运行的程序,而是运行在 Servlet 容器(如 Tomcat)中,由容器管理其生命周期,并调用其方法来处理 HTTP 请求。 ...

九月 25, 2022 · 12 分钟 · 2428 字 · yaomingye

Spring MVC 常用注解

Spring MVC 常用注解:企业级全场景用法与实战指南 🤔 1. 问题切入:一个订单查询接口 假设你在开发一个电商系统的订单查询接口,需要实现以下需求: 通过订单 ID 查询订单详情 支持按状态、时间范围过滤订单列表 接收 JSON 请求体来创建订单 处理参数校验失败时的错误返回 统一处理各类异常 以下是一个典型的 Spring MVC Controller 初版实现: @RestController @RequestMapping("/api/orders") public class OrderController { @GetMapping("/{id}") public Result<Order> getOrder(@PathVariable Long id) { // 查询订单 } @GetMapping public Result<Page<Order>> listOrders( @RequestParam(required = false) String status, @RequestParam(required = false) @DateTimeFormat(iso = DATE) LocalDate startDate, @RequestParam(required = false) @DateTimeFormat(iso = DATE) LocalDate endDate, @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "20") int size) { // 分页查询 } @PostMapping @ResponseStatus(HttpStatus.CREATED) public Result<Order> createOrder(@Validated @RequestBody CreateOrderRequest request) { // 创建订单 } } 短短几行代码用到了 10+ 个注解。这些注解各自承担什么职责?组合使用时有什么坑?在企业级项目中应该如何规范使用?这篇博客将系统性地回答这些问题。 ...

九月 24, 2022 · 12 分钟 · 2520 字 · yaomingye

Spring Boot企业开发高频注解完全指南

Spring Boot企业开发高频注解完全指南:从IoC容器到数据访问全覆盖 🤔 一、为什么需要这份注解清单 初学 Spring Boot 时,打开官方文档会看到上百个注解。但实际企业开发中,真正高频使用的注解只有其中一部分。很多注解你可能工作三五年也用不到一次。 本文筛选出企业开发中使用频率最高的 Spring 注解(不含 SpringMVC 和 SpringSecurity),每个注解都配有可运行的示例代码和一句话说明它的用途。不解释底层原理,只告诉你"这是什么、怎么用、什么时候用"。 注解来源范围:Spring Framework + Spring Boot + Spring Data JPA + Spring AOP + Spring Cache + Spring Scheduling + Spring Retry。 约定:下文所有示例均基于 Spring Boot 项目,包路径省略。示例中 @Service、@Repository 等注解未重复展示之处,默认已配合 @ComponentScan 自动扫描。 🗺️ 二、注解分类全景图 在实际进入每个注解之前,先用一张分类图建立全局认知: flowchart LR classDef root fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#bfdbfe,font-weight:bold; classDef branch fill:#2d1a05,stroke:#f59e0b,stroke-width:2px,color:#fde68a,font-weight:bold; classDef leaf fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#e5e7eb; ROOT[Spring注解体系] ROOT --> B1[1.IoC容器核心] ROOT --> B2[2.Boot启动配置] ROOT --> B3[3.AOP切面] ROOT --> B4[4.事务管理] ROOT --> B5[5.异步与定时] ROOT --> B6[6.缓存管理] ROOT --> B7[7.数据校验] ROOT --> B8[8.JPA数据访问] ROOT --> B9[9.事件监听] ROOT --> B10[10.测试支持] ROOT --> B11[11.条件装配] ROOT --> B12[12.重试机制] class ROOT root; class B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12 branch; 📦 三、Spring IoC 容器核心注解 IoC(控制反转)和 DI(依赖注入)是 Spring 的根基。以下是日常开发中必用的注解。 ...

九月 17, 2022 · 17 分钟 · 3415 字 · yaomingye
Cat Radio