当前位置: 首页 > ai >正文

Spring Framework 执行链路设计

前文我们分享了IoC、Web、数据访问、AOP、上下文等模块设计,聪明的码友已经想到了,该协同作业了。

至此协同作业我们从以下主流程进行展开:接收请求–>处理请求–>结果处理–>返回结果

一、Web 请求入口

场景:用户发起 HTTP 请求 → Spring Web 模块接收请求 → 调用 Controller 处理业务逻辑。

1. 核心流程

2. 核心组件与关键问题

组件主要功能
DispatcherServlet前端控制器,统一接收所有 HTTP 请求,协调其他组件完成请求处理流程(分发请求、调用处理器、渲染视图)。
HandlerMapping根据请求 URL 映射到对应的 Controller 方法(如通过 @GetMapping 注解),返回 HandlerExecutionChain(包含目标处理器和拦截器链)。
HandlerAdapter适配不同类型的处理器(如基于注解的 Controller 或传统 Servlet),执行方法并返回 ModelAndView
ViewResolver将逻辑视图名(如 userView)解析为实际的物理视图(如 JSP、Thymeleaf 模板)。
Interceptor实现横切关注点(如权限校验、日志记录),在请求处理前后插入自定义逻辑。
  • 问题 1:如何动态映射 URL 到 Controller?
  • Spring 解决方案
    • @GetMapping/@PostMapping 注解:通过注解定义 URL 路径和 HTTP 方法。
    • HandlerMappingRequestMappingHandlerMapping 解析注解并建立映射表。
  • 问题 2:如何处理异常?
  • Spring 解决方案
    • @ControllerAdvice:全局异常处理器,统一处理 Controller 层抛出的异常。
    • HandlerExceptionResolver:接口实现异常转换逻辑(如返回 JSON 错误响应)。

3. 示例代码

@RestController
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/user/{id}")public User getUser(@PathVariable String id) {return userService.findUserById(id);}
}@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public ResponseEntity<String> handleException(Exception ex) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());}
}

二、业务逻辑与 IoC 容器

问题:Controller 需要调用 Service 和 Repository,如何管理这些对象的生命周期?
解决方案:引入 IoC(控制反转),通过容器管理 Bean 的创建和依赖注入。

1. 核心流程

2. 核心组件与关键问题

组件主要功能
BeanFactorySpring IoC 容器的核心接口,负责管理 Bean 的创建、依赖注入和生命周期。
ApplicationContext扩展 BeanFactory,提供更丰富的功能(如事件发布、资源加载、国际化支持)。
BeanDefinition定义 Bean 的元数据(如类名、作用域、依赖关系),由容器解析后实例化 Bean。
BeanPostProcessor自定义 Bean 初始化/销毁逻辑(如 AOP 代理生成、属性赋值)。
  • 问题 1:循环依赖
  • 场景A 依赖 BB 依赖 A,导致初始化死循环。
  • Spring 解决方案
    • 三级缓存机制
      • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonObjects:已完全初始化的 Bean。
      • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#earlySingletonObjects:提前暴露的半成品 Bean。
      • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonFactories:通过 ObjectFactory 创建代理对象。
    • 代理对象介入:通过 AOP 生成代理对象,绕过循环依赖。
  • 问题 2:Bean 生命周期管理
  • Spring 提供
    • @PostConstruct:初始化后调用。
    • @PreDestroy:销毁前调用。
    • BeanPostProcessor:自定义初始化/销毁逻辑。

3. 示例代码

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;
}@Repository
public class UserRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;
}

三、数据访问模块

问题:Service 需要查询数据库,如何封装 SQL 操作并管理事务?
解决方案:引入 Spring Data Access 模块,通过模板模式和声明式事务实现。

1. 核心流程

2. 核心组件与关键问题

组件主要功能
JdbcTemplate封装 JDBC 操作(查询、更新等),减少模板代码冗余。
@Transactional声明式事务管理,通过 AOP 控制事务边界(如 REQUIREDREQUIRES_NEW 传播模式)。
DataSource管理数据库连接池(如 HikariCP),提供高性能的数据库连接。
RowMapper自定义结果集映射逻辑,将数据库记录转换为 Java 对象。
  • 问题 1:SQL 模板代码冗余
  • Spring 解决方案
    • JdbcTemplate:封装 JDBC 操作(查询、更新等),减少重复代码。
    • RowMapper:自定义结果集映射逻辑。
  • 问题 2:事务管理复杂
  • Spring 解决方案
    • @Transactional:通过 AOP 实现事务边界控制。
    • 事务传播行为:支持 REQUIREDREQUIRES_NEW 等传播模式。

3. 示例代码

@Repository
public class UserRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;public User findUserById(String id) {return jdbcTemplate.queryForObject("SELECT * FROM users WHERE id = ?",new Object[]{id},(rs, rowNum) -> new User(rs.getString("name")));}
}@Service
public class UserService {@Transactionalpublic void updateUser(User user) {userRepository.update(user);}
}

四、上下文模块

问题:如何统一管理配置、事件、资源加载?
解决方案:引入 ApplicationContext,作为 Spring 容器的核心接口。

1. 核心组件与关键问题

组件主要功能
ApplicationContext管理应用配置、资源加载、事件发布和国际化支持。
PropertySourcesPlaceholderConfigurer解析 application.properties 中的占位符(如 ${spring.datasource.url})。
ApplicationEventPublisher发布事件(如 ContextRefreshedEvent),支持事件监听器(ApplicationListener)异步处理。
MessageSource提供多语言资源管理,支持国际化(i18n)。
  • 问题 1:配置文件加载失败
    Spring 解决方案
    • PropertySourcesPlaceholderConfigurer:解析 application.properties 中的占位符。
    • @PropertySource:自定义配置文件路径。
  • 问题 2:事件监听效率低
    Spring 解决方案
    • ApplicationListener:异步监听事件(通过 @Async 实现)。

2. 示例代码

@Configuration
public class AppConfig {@Beanpublic DataSource dataSource() {return DataSourceBuilder.create().build();}
}public class MyCustomListener implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {System.out.println("应用启动完成");}
}

五、AOP 模块

问题:如何将日志、事务等公共逻辑与业务代码解耦?
解决方案:引入 AOP(面向切面编程),通过拦截器链实现横切关注点管理。

1. 核心流程

2. 核心组件与关键问题

组件主要功能
@Aspect定义切面类,封装横切关注点(如日志、事务)。
@Pointcut定义切入点表达式(如 execution(* com.albert.service.*.*(..))),指定切面逻辑的应用范围。
MethodInterceptor通过责任链模式执行通知逻辑(如 @Before@After)。
ProxyFactory动态生成代理对象(JDK 动态代理或 CGLIB 代理)。
  • 问题 1:切点表达式匹配错误
  • Spring 解决方案
    • AspectJ 表达式语法:精确控制切点范围(如 execution(* com.albert.service.*.*(..)))。
  • 问题 2:代理性能问题
  • Spring 解决方案
    • JDK 动态代理:适用于接口类。
    • CGLIB 代理:适用于无接口类(需注意 final 方法限制)。

3. 示例代码

@Aspect
@Component
public class MyLogAspect {@Before("execution(* com.albert.service.*.*(..))")public void logBefore(JoinPoint joinPoint) {System.out.println("方法调用前: " + joinPoint.getSignature().getName());}
}

六、整体执行链路总结

1. Spring 容器启动阶段(资源准备)

1.1 Spring 容器初始化
  • ApplicationContext 加载配置
    • 读取 application.properties 或 XML 配置文件,解析 Bean 定义(BeanDefinition)。
    • 初始化 BeanFactory,注册所有 Bean 的定义信息。
  • 资源预加载
    • 数据库连接池初始化(如 Druid):
      • 根据配置创建数据库连接池,建立初始连接,确保后续请求可直接使用。
    • AOP 代理对象生成
      • 通过 InstantiationAwareBeanPostProcessor 在 Bean 实例化前生成代理对象(如 AOP 代理)。
      • 示例:postProcessBeforeInstantiation 返回代理对象,跳过默认实例化。
  • Bean 实例化与依赖注入
    • Bean 实例化
      • 调用构造函数创建 Bean 实例(或通过工厂方法)。
      • 通过 BeanPostProcessor 在实例化前后进行拦截(如属性校验、动态代理)。
    • 依赖注入(DI)
      • 填充属性(@Autowired 注解字段)。
      • 通过 postProcessProperties 修改属性值(如解密敏感数据)。
  • Bean 初始化
    • 调用 @PostConstruct 方法或 init-method
    • 应用 AOP 通知(如 @Around@After)。
1.2 Web 模块初始化
  • DispatcherServlet 注册:
    • DispatcherServlet 注册为处理 HTTP 请求的前端控制器。
  • HandlerMapping 配置:
    • 将 URL 映射到 Controller 方法(如 @GetMapping 注解)。
  • ViewResolver 配置:
    • 配置逻辑视图名到物理视图的映射规则(如 Thymeleaf 模板路径)。
1.3 事务管理器初始化
  • 配置 PlatformTransactionManager(如 DataSourceTransactionManager)。
  • 注册事务注解驱动(@EnableTransactionManagement)。
1.4 事件监听器注册
  • 注册 ApplicationListener 监听应用事件(如 ContextRefreshedEvent)。

2. 请求处理阶段(运行时流程)

2.1 客户端发送 HTTP 请求
  • 请求由 DispatcherServlet 接收,进入 Spring MVC 流程。
2.2 请求映射与处理器调用
  • HandlerMapping 查找处理器:
    • 根据 URL 匹配对应的 Controller 方法(@GetMapping/@PostMapping)。
  • HandlerAdapter 调用处理器:
    • 执行 Controller 方法,获取 ModelAndView
2.3 业务逻辑执行
  • Service 层调用 Repository
    • 通过依赖注入的 DAO 或 JPA Repository 访问数据库。
  • 事务管理
    • @Transactional 注解触发事务边界(如开启事务、提交/回滚)。
2.4 AOP 拦截器链执行
  • 通知逻辑执行
    • @Before:前置增强(如权限校验)。
    • @After:后置增强(如日志记录)。
    • @Around:环绕增强(如性能监控)。
  • 异常处理
    • @AfterThrowing 捕获异常并执行自定义逻辑。
2.5 视图解析与响应返回
  • ViewResolver 解析视图:
    • 将逻辑视图名(如 userView)转换为物理视图(如 Thymeleaf 模板路径)。
  • 渲染视图并返回响应
    • Model 数据传递给视图模板,生成 HTML 响应。

附录:各模块设计引入后的新问题与解决

模块引入后的新问题Spring 解决方案
Web请求映射冲突、异常处理不统一@RequestMapping 注解、@ControllerAdvice 全局异常处理器
IoC循环依赖、Bean 初始化失败三级缓存机制、@Lazy 延迟加载、@PostConstruct 自定义初始化
数据访问SQL 模板代码冗余、事务管理复杂JdbcTemplate@Transactional 声明式事务
AOP切点匹配错误、代理性能问题AspectJ 表达式语法、JDK/CGLIB 代理选择
上下文配置文件加载失败、事件监听效率低PropertySourcesPlaceholderConfigurer@Async 异步事件监听
http://www.xdnf.cn/news/14070.html

相关文章:

  • PC 基准测试工具 3D Mark 登陆 macOS
  • Boost dlib opencv vs2022 C++ 源码安装集成配置
  • Missing Semester计算机教育中缺失的一课:Vim
  • 端到端记忆网络 vs 神经图灵机:外部记忆的两种哲学之争
  • 腾讯云配置了国内镜像依然docker search失败
  • Vue3 + JavaScript 父组件点击按钮触发子组件事件方法
  • pytorch2.6安装
  • 编程之礼乐
  • Karate UI测试之驱动配置
  • 嵌入式学习笔记C语言阶段--14可变长数组
  • HTTP 缓存策略:强缓存与协商缓存的深入解析
  • Docker 部署 PostgreSQL 指南
  • C++ RPC 远程过程调用详细解析
  • Python爬虫-爬取票牛明星演唱会数据,进行数据分析
  • 日志分割问题
  • 卷积神经网络的参数量及尺度变化计算
  • [每周一更]-(第147期):使用 Go 语言实现 JSON Web Token (JWT)
  • WWDC25中的HDR技术洞察
  • 基于深度学习的智能图像分类系统:从零开始构建
  • BeckHoff <---> Keyence (LJ-8000) 2D相机 Profinet 通讯
  • PyTorch框架详解(1)
  • 韦东奕论文解读
  • 开机自启动文件夹
  • Vue嵌套路由
  • 机器学习入门 | 机器学习方法与模型概述
  • 【图纸管理教程-3】编码统一,效率倍增!解决一物多码问题
  • Manus邀请薅羊毛
  • WPF加载文本文件时如何设置WebBrowser的字体
  • 第三章支线八 ·构建之巅 · 工具链与打包炼金术
  • ELK日志文件分析系统——概念