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

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 异步事件监听

相关文章:

  • 大模型笔记1:大致了解大模型
  • MLLM常见概念通俗解析(五)
  • 【Redis】Redis的启航之路:Ubantu操作系统下安装Redis
  • ABP vNext 多语言与本地化:动态切换、资源继承与热更新
  • 微信小程序使用图片实现红包雨功能
  • error:MISCONF Redis is configured to save RDB snapshots
  • 计算机网络-自顶向下—第五章数据链路层重点复习笔记
  • 《高并发系统性能优化三板斧:缓存 + 异步 + 限流》
  • Nginx+keepalived主从,双主架构
  • git-build-package 工具代码详细解读
  • Git常用命令摘要
  • 青少年编程与数学 01-011 系统软件简介 19 SSMS 数据库管理工具
  • 【AS32系列MCU调试教程】性能优化:Eclipse环境下AS32芯片调试效率提升
  • Java 与 MySQL 性能优化:Linux服务器上MySQL性能指标解读与监控方法
  • Spring MVC 中日期格式转换的两种实用方法
  • ​​实时人脸检测与人脸关键点识别系统实现
  • 简历模板3——数据挖掘工程师5年经验
  • 【机器学习与数据挖掘实战 | 医疗】案例16:基于K-Means聚类的医疗保险的欺诈发现
  • 提的缺陷开发不改,测试该怎么办?
  • shell编程语言-1 shell脚本基础
  • 1688开山网一起做网站/软文怎么写比较吸引人
  • 没有备案的网站百度能收录吗/宁波网站推广优化哪家正规
  • 网站建设素材/营销推广活动方案
  • 网站的类别/百度广告服务商
  • 企业网站源码 php/百度新闻发布平台
  • 网站页面 原则/seo公司推广