找回密码
 立即注册
首页 业界区 业界 从零手搓一个类Spring框架,彻底搞懂Spring核心原理 ...

从零手搓一个类Spring框架,彻底搞懂Spring核心原理

府扔影 2026-1-24 19:10:07
从零手搓一个类Spring框架,彻底搞懂Spring核心原理

作者:JarryLi
适合读者:Java工程师以及对设计模式和框架原理感兴趣的同学。如果你想学习和运用设计模式,熟悉Spring框架是最佳的途径之一。
前言

还记得很多年前刚接触Spring的时候,我觉得很神奇:通过xml配置就可以自动注入对象,甚至一个@Autowired注解就能搞定?AOP 还能在不侵入业务代码的情况下统一加日志和事务?那时主流还是 EJB 体系,使用原生Servlet、JSP以及Struts框架。面对 IoC、DI 这些看似"魔法"的能力,不免想一探究竟:它们到底是怎么实现的?
从那时起,开始学习Spring源码。真正看进去才发现,这些并不神奇,而是大量工程化设计的结果:层层抽象、接口解耦、经典设计模式的复用。源码规模不小,很难一口气看完,只能带着问题一点点学习。
纸上得来终觉浅,绝知此事要躬行。于是参照Spring框架写了一个简化版的SpringWind框架,用最简洁的代码实现 Spring 的核心功能,让每个想深入理解框架原理的开发者都能看懂
在这个过程中,不仅搞懂了IoC、DI、AOP这些核心概念,以及Bean生命周期、DispatcherServlet控制器与ApplicationContext容器体系,还深刻理解了为什么Spring要这样设计。现在,我把这些实践经验和心得分享出来,希望能帮助你快速掌握Spring的核心原理。
代码仓库: https://github.com/microwind/design-patterns/tree/main/practice-projects/springwind
目录


  • 关于 SpringWind 框架
  • Spring的设计理念
  • Spring的核心特性
  • 深入理解Spring框架
  • 参照Spring框架设计Springwind的架构
  • SpringWind 与 Spring MVC 的对比
  • Springwind框架有什么用
  • Springwind的项目结构
  • Springwind使用实践
  • 快速开始
  • Springwind改进点
关于 SpringWind 框架

SpringWind 是一个教学性质的轻量级 Java Web 框架,旨在帮助开发者深入理解 Spring 框架的核心原理。通过从零开始实现 Spring 的核心机制(IoC、DI、AOP、三级缓存、MVC等),让框架不再是"黑盒子",而是可以完全理解的"白盒子"。
框架定位

SpringWind 不是为了替代 Spring Framework,而是作为:

  • 学习工具:是理解 Spring 核心原理的最佳实践
  • 教学框架:通过由浅入深的方式,让你逐渐理解Spring框架
  • 快速原型:对于一些小型项目,那么Springwind更加轻量简便
  • 探索平台:可以验证一些新架构思想与理念,不断创新
核心特性

SpringWind 实现了 Spring Framework 的以下核心功能:
特性说明对应 Spring 功能IoC 容器自动扫描、注册和管理 Bean 的生命周期ApplicationContext依赖注入通过 @Autowired 实现自动装配Dependency Injection组件注解@Component、@Service、@Controller、@RepositoryStereotype AnnotationsMVC 模式模拟 Spring MVC 的请求处理机制Spring MVC请求映射@RequestMapping 实现 URL 到方法的映射Request Mapping参数绑定@PathVariable、@RequestParam、@RequestBodyParameter BindingAOP 支持基于 JDK/CGLIB 的动态代理实现切面编程Spring AOPBeanPostProcessorBean 的前置和后置处理,支持生命周期干预BeanPostProcessorSmartInstantiationAwareBeanPostProcessor支持在 Bean 实例化早期创建代理,解决循环依赖SmartInstantiationAwareBeanPostProcessor三级缓存优雅解决循环依赖问题Circular Dependency ResolutionJDBC 模板简化数据库操作的模板类JdbcTemplateJSON 响应自动序列化对象为 JSON@ResponseBody与 Spring Framework 的关系

SpringWind 参考了 Spring Framework 的设计思想,但做了大量简化:
相同点:

  • 核心设计理念(IoC、DI、AOP)
  • 注解驱动开发
  • 分层架构(Controller-Service-Dao)
  • 三级缓存解决循环依赖
  • 模板方法封装样板代码
不同点:

  • 代码规模:SpringWind 代码约 4000 行,Spring Framework 超过 50 万行
  • 功能范围:SpringWind 聚焦核心功能,Spring 提供全面的企业级特性
  • 复杂度:SpringWind 去除了大量抽象层次,更易理解
  • 生产就绪:Spring 经过大规模验证,SpringWind 主要用于学习
技术栈
  1. 核心技术:
  2. ├── Java 17+<bean id="userService" >
  3.     <property name="userDao" ref="userDao"/>
  4. </bean>
  5. <bean id="userDao" /><bean id="userService" >
  6.     <property name="userDao" ref="userDao"/>
  7. </bean>
  8. <bean id="userDao" /><bean id="userService" >
  9.     <property name="userDao" ref="userDao"/>
  10. </bean>
  11. <bean id="userDao" /><bean id="userService" >
  12.     <property name="userDao" ref="userDao"/>
  13. </bean>
  14. <bean id="userDao" /><bean id="userService" >
  15.     <property name="userDao" ref="userDao"/>
  16. </bean>
  17. <bean id="userDao" /># 现代 Java 特性
  18. ├── Jakarta Servlet API 6.1<bean id="userService" >
  19.     <property name="userDao" ref="userDao"/>
  20. </bean>
  21. <bean id="userDao" /> # Web 容器标准
  22. ├── CGLIB 3.3.0<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /> # 字节码增强(AOP)
  35. ├── SLF4J + Logback<bean id="userService" >
  36.     <property name="userDao" ref="userDao"/>
  37. </bean>
  38. <bean id="userDao" /><bean id="userService" >
  39.     <property name="userDao" ref="userDao"/>
  40. </bean>
  41. <bean id="userDao" /><bean id="userService" >
  42.     <property name="userDao" ref="userDao"/>
  43. </bean>
  44. <bean id="userDao" /> # 日志框架
  45. └── Jackson 2.18.2<bean id="userService" >
  46.     <property name="userDao" ref="userDao"/>
  47. </bean>
  48. <bean id="userDao" /><bean id="userService" >
  49.     <property name="userDao" ref="userDao"/>
  50. </bean>
  51. <bean id="userDao" /><bean id="userService" >
  52.     <property name="userDao" ref="userDao"/>
  53. </bean>
  54. <bean id="userDao" />  # JSON 序列化
  55. 构建工具:
  56. └── Maven 3.6+
  57. 运行环境:
  58. ├── Embedded Tomcat 11<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" /> # 嵌入式 Web 服务器
  65. └── H2 / MySQL<bean id="userService" >
  66.     <property name="userDao" ref="userDao"/>
  67. </bean>
  68. <bean id="userDao" /><bean id="userService" >
  69.     <property name="userDao" ref="userDao"/>
  70. </bean>
  71. <bean id="userDao" /><bean id="userService" >
  72.     <property name="userDao" ref="userDao"/>
  73. </bean>
  74. <bean id="userDao" /><bean id="userService" >
  75.     <property name="userDao" ref="userDao"/>
  76. </bean>
  77. <bean id="userDao" /> # 数据库(可选)
复制代码
SpringWind 与 Spring MVC 注解对照表

为了降低学习成本,SpringWind 的注解与 Spring MVC 保持一致:
SpringWind 注解Spring MVC 注解作用示例@Component@Component标记通用组件@Component@Service@Service标记服务层组件@Service@Controller@Controller标记控制器组件@Controller@Repository@Repository标记数据访问层组件@Repository@Autowired@Autowired自动注入依赖@Autowired private UserDao dao;@RequestMapping@RequestMapping映射 HTTP 请求@RequestMapping("/user")@PathVariable@PathVariable绑定路径变量@PathVariable("id") Long id@RequestParam@RequestParam绑定请求参数@RequestParam("name") String name@RequestBody@RequestBody绑定请求体(JSON)@RequestBody User user@ResponseBody@ResponseBody返回 JSON 响应@ResponseBody@Aspect@Aspect标记切面类@Aspect@Before@Before前置通知@Before("com.example.*")@After@After后置通知@After("com.example.*")@Around@Around环绕通知@Around("com.example.*")使用示例:
  1. // 定义 Controller
  2. @Controller
  3. @RequestMapping("/user")
  4. public class UserController {
  5. <bean id="userService" >
  6.     <property name="userDao" ref="userDao"/>
  7. </bean>
  8. <bean id="userDao" />@Autowired
  9. <bean id="userService" >
  10.     <property name="userDao" ref="userDao"/>
  11. </bean>
  12. <bean id="userDao" />private UserService userService;  // 自动注入
  13. <bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />@RequestMapping("/get")
  17. <bean id="userService" >
  18.     <property name="userDao" ref="userDao"/>
  19. </bean>
  20. <bean id="userDao" />@ResponseBody
  21. <bean id="userService" >
  22.     <property name="userDao" ref="userDao"/>
  23. </bean>
  24. <bean id="userDao" />public User getUser(@RequestParam("id") Long id) {
  25. <bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />return userService.getUserById(id);
  32. <bean id="userService" >
  33.     <property name="userDao" ref="userDao"/>
  34. </bean>
  35. <bean id="userDao" />}
  36. <bean id="userService" >
  37.     <property name="userDao" ref="userDao"/>
  38. </bean>
  39. <bean id="userDao" />@RequestMapping("/detail/{id}")
  40. <bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />@ResponseBody
  44. <bean id="userService" >
  45.     <property name="userDao" ref="userDao"/>
  46. </bean>
  47. <bean id="userDao" />public User getUserDetail(@PathVariable("id") Long id) {
  48. <bean id="userService" >
  49.     <property name="userDao" ref="userDao"/>
  50. </bean>
  51. <bean id="userDao" /><bean id="userService" >
  52.     <property name="userDao" ref="userDao"/>
  53. </bean>
  54. <bean id="userDao" />return userService.getUserById(id);
  55. <bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />}
  59. <bean id="userService" >
  60.     <property name="userDao" ref="userDao"/>
  61. </bean>
  62. <bean id="userDao" />@RequestMapping("/create")
  63. <bean id="userService" >
  64.     <property name="userDao" ref="userDao"/>
  65. </bean>
  66. <bean id="userDao" />@ResponseBody
  67. <bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" />public User createUser(@RequestBody User user) {
  71. <bean id="userService" >
  72.     <property name="userDao" ref="userDao"/>
  73. </bean>
  74. <bean id="userDao" /><bean id="userService" >
  75.     <property name="userDao" ref="userDao"/>
  76. </bean>
  77. <bean id="userDao" />return userService.createUser(user);
  78. <bean id="userService" >
  79.     <property name="userDao" ref="userDao"/>
  80. </bean>
  81. <bean id="userDao" />}
  82. }
复制代码
如果你熟悉 Spring MVC,就能零学习成本理解 SpringWind!你理解了Springwind也就明白了Spring。
学习路径建议

第一步:快速体验(10分钟)

  • 运行示例项目,看看效果
  • 访问几个 API 接口,理解请求流程
第二步:理解核心原理(1-2小时)

  • 阅读本文档的"Spring的设计理念"和"Spring的核心特性"
  • 打断点调试,观察 Bean 的创建和依赖注入过程
  • 理解三级缓存如何解决循环依赖
第三步:深入源码(3-5小时)

  • 阅读 SpringWindApplicationContext.java(IoC 容器核心)
  • 阅读 AspectProcessor.java(AOP 代理创建)
  • 阅读 DispatcherServlet.java(MVC 请求分发)
  • 阅读 JdbcTemplate.java(JDBC 模板方法)
第四步:动手实践(1-2天)

  • 基于 SpringWind 写一个小项目
  • 尝试添加新功能(如事务支持)
  • 对比 Spring Framework 源码,理解设计差异
第五步:给 Spring 贡献代码(进阶)

  • 理解 Spring 的设计思想后,可以参与 Spring 社区
  • 提交 Bug 修复或新功能的 Pull Request
Spring的设计理念

在开始造轮子之前,我们得先理解Spring为什么要这样设计。很多人觉得Spring框架复杂,但其实它的核心理念非常简单。
1. 控制反转(IoC)- 别再自己new对象了

传统做法的痛点:
  1. // 传统方式:自己管理对象
  2. public class UserService {
  3. <bean id="userService" >
  4.     <property name="userDao" ref="userDao"/>
  5. </bean>
  6. <bean id="userDao" />private UserDao userDao = new UserDaoImpl();  // 硬编码依赖
  7. <bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />private EmailService emailService = new EmailServiceImpl();   // 硬编码依赖
  11. <bean id="userService" >
  12.     <property name="userDao" ref="userDao"/>
  13. </bean>
  14. <bean id="userDao" />public void registerUser(User user) {
  15. <bean id="userService" >
  16.     <property name="userDao" ref="userDao"/>
  17. </bean>
  18. <bean id="userDao" /><bean id="userService" >
  19.     <property name="userDao" ref="userDao"/>
  20. </bean>
  21. <bean id="userDao" />userDao.save(user);
  22. <bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />emailService.sendWelcomeEmail(user);
  29. <bean id="userService" >
  30.     <property name="userDao" ref="userDao"/>
  31. </bean>
  32. <bean id="userDao" />}
  33. }
复制代码
这样写有什么问题?
其实这样写本身从理解来讲最好理解,但不便于扩展。项目一大,后续维护就变得麻烦。

  • 耦合度高:UserService强依赖具体的实现类
  • 难以测试:无法替换成Mock对象做单元测试
  • 配置混乱:数据库连接、邮件配置都硬编码在代码里
Spring的解决方案:
  1. // Spring方式:依赖注入
  2. @Service
  3. public class UserService {
  4. <bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />@Autowired
  8. <bean id="userService" >
  9.     <property name="userDao" ref="userDao"/>
  10. </bean>
  11. <bean id="userDao" />private UserDao userDao;  // 由容器注入
  12. <bean id="userService" >
  13.     <property name="userDao" ref="userDao"/>
  14. </bean>
  15. <bean id="userDao" />@Autowired
  16. <bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />private EmailService emailService;
  20. <bean id="userService" >
  21.     <property name="userDao" ref="userDao"/>
  22. </bean>
  23. <bean id="userDao" />public void registerUser(User user) {
  24. <bean id="userService" >
  25.     <property name="userDao" ref="userDao"/>
  26. </bean>
  27. <bean id="userDao" /><bean id="userService" >
  28.     <property name="userDao" ref="userDao"/>
  29. </bean>
  30. <bean id="userDao" />userDao.save(user);
  31. <bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />emailService.sendWelcomeEmail(user);
  38. <bean id="userService" >
  39.     <property name="userDao" ref="userDao"/>
  40. </bean>
  41. <bean id="userDao" />}
  42. }
复制代码
现在,对象的创建和管理交给了IoC容器,业务代码只需要声明"我需要什么",而不用关心"怎么创建"。这就是控制反转的核心思想。
2. 面向切面编程(AOP)- 横切关注点分离

假设你要给所有Service方法加日志,传统做法是这样:
  1. public class UserService {
  2. <bean id="userService" >
  3.     <property name="userDao" ref="userDao"/>
  4. </bean>
  5. <bean id="userDao" />public void registerUser(User user) {
  6. <bean id="userService" >
  7.     <property name="userDao" ref="userDao"/>
  8. </bean>
  9. <bean id="userDao" /><bean id="userService" >
  10.     <property name="userDao" ref="userDao"/>
  11. </bean>
  12. <bean id="userDao" />System.out.println("开始执行registerUser");  // 日志代码
  13. <bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />long start = System.currentTimeMillis();<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />  // 性能监控代码
  23. <bean id="userService" >
  24.     <property name="userDao" ref="userDao"/>
  25. </bean>
  26. <bean id="userDao" /><bean id="userService" >
  27.     <property name="userDao" ref="userDao"/>
  28. </bean>
  29. <bean id="userDao" />userDao.save(user);  // 真正的业务逻辑
  30. <bean id="userService" >
  31.     <property name="userDao" ref="userDao"/>
  32. </bean>
  33. <bean id="userDao" /><bean id="userService" >
  34.     <property name="userDao" ref="userDao"/>
  35. </bean>
  36. <bean id="userDao" />long end = System.currentTimeMillis();
  37. <bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />System.out.println("执行完成,耗时: " + (end - start) + "ms");
  44. <bean id="userService" >
  45.     <property name="userDao" ref="userDao"/>
  46. </bean>
  47. <bean id="userDao" />}
  48. }
复制代码
业务代码和日志、监控代码混在一起,非常臃肿。而且如果有100个方法,就得重复100遍这些代码。
AOP的解决方案:
  1. @Aspect
  2. public class LoggingAspect {
  3. <bean id="userService" >
  4.     <property name="userDao" ref="userDao"/>
  5. </bean>
  6. <bean id="userDao" />@Before("com.example.service.*.*")
  7. <bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />public void logBefore(Method method) {
  11. <bean id="userService" >
  12.     <property name="userDao" ref="userDao"/>
  13. </bean>
  14. <bean id="userDao" /><bean id="userService" >
  15.     <property name="userDao" ref="userDao"/>
  16. </bean>
  17. <bean id="userDao" />System.out.println("开始执行: " + method.getName());
  18. <bean id="userService" >
  19.     <property name="userDao" ref="userDao"/>
  20. </bean>
  21. <bean id="userDao" />}
  22. <bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />@After("com.example.service.*.*")
  26. <bean id="userService" >
  27.     <property name="userDao" ref="userDao"/>
  28. </bean>
  29. <bean id="userDao" />public void logAfter(Method method) {
  30. <bean id="userService" >
  31.     <property name="userDao" ref="userDao"/>
  32. </bean>
  33. <bean id="userDao" /><bean id="userService" >
  34.     <property name="userDao" ref="userDao"/>
  35. </bean>
  36. <bean id="userDao" />System.out.println("执行完成: " + method.getName());
  37. <bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />}
  41. }
  42. // 业务代码保持纯净
  43. @Service
  44. public class UserService {
  45. <bean id="userService" >
  46.     <property name="userDao" ref="userDao"/>
  47. </bean>
  48. <bean id="userDao" />public void registerUser(User user) {
  49. <bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" /><bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" />userDao.save(user);  // 只关注业务逻辑
  56. <bean id="userService" >
  57.     <property name="userDao" ref="userDao"/>
  58. </bean>
  59. <bean id="userDao" />}
  60. }
复制代码
日志、事务、权限校验这些横切关注点被抽离出来,业务代码变得清爽多了。
3. 约定优于配置 - 少写XML,多用注解

早期的Spring需要写大量XML配置:
  1. <bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />
复制代码
现在只需要:
  1. @Servicepublic class UserService {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@Autowired<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private UserDao userDao;}
复制代码
一个注解就搞定了。这就是约定优于配置的威力。
4. 模板方法模式 - 封装样板代码

JDBC操作有大量的样板代码:
  1. // 传统JDBC:50多行代码Connection conn = null;PreparedStatement stmt = null;ResultSet rs = null;try {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />conn = dataSource.getConnection();<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />stmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?");<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />stmt.setLong(1, userId);<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />rs = stmt.executeQuery();<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />if (rs.next()) {<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />return new User(rs);<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />}} catch (SQLException e) {<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />throw new RuntimeException(e);} finally {<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />if (rs != null) try { rs.close(); } catch (SQLException e) {}<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />if (stmt != null) try { stmt.close(); } catch (SQLException e) {}<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />if (conn != null) try { conn.close(); } catch (SQLException e) {}}
复制代码
Spring JdbcTemplate:
  1. // 简洁的JdbcTemplate:2行代码User user = jdbcTemplate.queryForObject(<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />"SELECT * FROM users WHERE id = ?",<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />(rs, rowNum) -> new User(rs),<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />userId);
复制代码
获取连接、关闭资源这些固定步骤被封装了,你只需要专注于SQL和结果映射。
Spring的核心特性

在理解了Spring的设计理念后,我们来看看它的核心特性是如何实现的。
IoC容器 - 对象的大管家

IoC容器就像一个对象工厂,负责:

  • 扫描组件:找到所有带@Component、@Service等注解的类
  • 注册Bean定义:把类的元信息存起来
  • 实例化Bean:通过反射创建对象
  • 依赖注入:把依赖的对象注入进去
  • 生命周期管理:管理Bean的创建和销毁
Bean的生命周期:
---title: Bean的生命周期(完整流程)---graph LR<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />A[扫描组件] --> B[注册BeanDefinition]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />B --> C[实例化Bean
调用构造器]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />C --> D["放入三级缓存
ObjectFactory
关键!"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />D --> E["依赖注入
@Autowired字段
可能触发循环依赖"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />E --> F["前置处理器
postProcessBefore
Initialization"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />F --> G["初始化方法
@PostConstruct"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />G --> H["后置处理器
postProcessAfter
Initialization
AOP代理创建"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />H --> I["放入一级缓存
清理二三级缓存"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />I --> J[Bean就绪
可被使用]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />J --> K["销毁
@PreDestroy"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style A fill:#e1f5fe,stroke:#01579b,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style B fill:#fff3e0,stroke:#f57c00,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style C fill:#f1f8e9,stroke:#7cb342,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style D fill:#fff8e1,stroke:#ffb300,stroke-width:3px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style E fill:#fce4ec,stroke:#c2185b,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style F fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style G fill:#e8f5e8,stroke:#388e3c,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style H fill:#ffe0b2,stroke:#e65100,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style I fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style J fill:#a5d6a7,stroke:#00695c,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style K fill:#FFE4E1,stroke:#B20E7E,stroke-width:2px关键步骤说明

  • 步骤4(三级缓存):这是解决循环依赖的关键,放入的是ObjectFactory而非Bean本身
  • 步骤5(依赖注入):如果依赖的Bean正在创建,会从三级缓存获取早期引用,触发循环依赖解决机制
  • 步骤8(后置处理器):AOP代理通常在此创建,但如果在步骤4的getEarlyBeanReference中已创建,则跳过
在SpringWind中,我们用一个核心类SpringWindApplicationContext来实现这些功能:
  1. public class SpringWindApplicationContext {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// 一级缓存:完整初始化的Bean对象<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private Map singletonObjects = new ConcurrentHashMap();<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />// 二级缓存:早期Bean引用(用于解决循环依赖)<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />private Map earlySingletonObjects = new ConcurrentHashMap();<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />// 三级缓存:ObjectFactory工厂(用于延迟生成早期引用,支持AOP)<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />private Map clazz = bean.getClass();<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />// 扫描所有字段<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />for (Field field : clazz.getDeclaredFields()) {<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />if (!field.isAnnotationPresent(Autowired.class)) {<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />continue;<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />}<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />// 根据类型从容器中查找Bean<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />Object dependency = getBean(field.getType());<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />if (dependency == null) {<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" /><bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" />throw new BeanNotFoundException("找不到依赖: " + field.getType());<bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" /><bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" />}<bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" /><bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" />// 通过反射设置字段值<bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" /><bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" />field.setAccessible(true);<bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" /><bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" />field.set(bean, dependency);<bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" />}}
复制代码
流程很简单:

  • 找到所有带@Autowired的字段
  • 根据字段类型从容器中查找对应的Bean
  • 通过反射把Bean注入进去
AOP - 动态代理的实现

AOP的核心是动态代理。SpringWind支持两种代理方式:
1. JDK动态代理(基于接口)
  1. // 如果目标类实现了接口,目标类实现的接口数量大于0if (interfaces.length > 0) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// 使用JDK动态代理创建代理对象<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />return Proxy.newProxyInstance(<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" /><bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />// 指定类加载器,用于加载动态生成的代理类<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />classLoader,<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />// 代理类需要实现的接口数组,代理对象需要实现接口的所有方法<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />interfaces,<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />// 创建调用处理器,将目标对象和切面列表传入<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />// AopInvocationHandler负责处理方法调用时的切面逻辑<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />new AopInvocationHandler(target, aspects)<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />);}
复制代码
2. CGLIB代理(基于继承)
  1. // 创建A的过程(对应代码SpringWindApplicationContext.java)
  2. 1. getBean("beanA") 被调用
  3. 2. 检查一级缓存singletonObjects → 未找到
  4. 3. 检查是否正在创建 → 不在,继续创建流程
  5. 4. 标记A正在创建:singletonsCurrentlyInCreation.add("beanA")
  6. 5. 实例化A:调用构造器,得到原始对象(此时尚未注入依赖)
  7. 6. **关键步骤**:将ObjectFactory放入三级缓存
  8.    singletonFactories.put("beanA", () -> getEarlyBeanReference("beanA", rawBeanA))
  9.    // 注意:此时放入的是工厂对象,不是Bean本身!
  10. 7. 开始为A注入依赖:doDependencyInjection(beanA)
  11. 8. 发现A依赖B,调用getBean("beanB")
  12.    // 创建B的过程(嵌套在A的创建过程中)
  13.    9. 检查一级缓存 → 未找到B
  14.    10. 标记B正在创建:singletonsCurrentlyInCreation.add("beanB")
  15.    11. 实例化B:得到原始对象
  16.    12. 将ObjectFactory放入三级缓存:
  17.        singletonFactories.put("beanB", () -> getEarlyBeanReference("beanB", rawBeanB))
  18.    13. 开始为B注入依赖:发现B依赖A,调用getBean("beanA")
  19.       // 循环依赖检测与解决(关键!)
  20.       14. 检查一级缓存 → 未找到A(因为A还没完成初始化)
  21.       15. 发现A在正在创建集合中:singletonsCurrentlyInCreation.contains("beanA") = true
  22.       16. 检查二级缓存earlySingletonObjects → 未找到
  23.       17. 检查三级缓存singletonFactories → 找到A的ObjectFactory ✓
  24.       18. **调用ObjectFactory.getObject()**
  25.           → 内部调用getEarlyBeanReference("beanA", rawBeanA)
  26.           → 如果A需要AOP代理,SmartInstantiationAwareBeanPostProcessor会在此创建代理
  27.           → 返回A的早期引用(可能是原始对象,也可能是代理对象)
  28.       19. 将A的早期引用放入二级缓存:earlySingletonObjects.put("beanA", earlyA)
  29.       20. 从三级缓存移除:singletonFactories.remove("beanA")
  30.       21. 返回A的早期引用给B ✓
  31.    22. B完成依赖注入(注入了A的早期引用)
  32.    23. B执行前置处理器:applyBeanPostProcessorsBeforeInitialization
  33.    24. B执行@PostConstruct初始化方法
  34.    25. B执行后置处理器:applyBeanPostProcessorsAfterInitialization(AOP代理可能在此创建)
  35.    26. B完成创建,放入一级缓存:singletonObjects.put("beanB", beanB)
  36.    27. 清理B的二、三级缓存
  37.    28. 从正在创建集合移除:singletonsCurrentlyInCreation.remove("beanB")
  38. 29. getBean("beanB") 返回完整的B → A成功注入B
  39. 30. A完成依赖注入
  40. 31. A执行前置处理器
  41. 32. A执行@PostConstruct初始化方法
  42. 33. A执行后置处理器(如果A之前已在getEarlyBeanReference中创建了代理,这里会跳过)
  43. 34. A完成创建,放入一级缓存:singletonObjects.put("beanA", beanA)
  44. 35. 清理A的二、三级缓存
  45. 36. 从正在创建集合移除:singletonsCurrentlyInCreation.remove("beanA")
  46. 37. 完成!A和B都成功创建,循环依赖已解决
复制代码
代理的工作流程:
---title: AOP方法调用流程---flowchart LR<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />A["客户端调用方法"] --> B["代理对象拦截"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />B --> C["执行@Before通知
(前置增强)"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />C --> D["调用目标方法
(真正的业务逻辑)"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />D --> E["执行@After通知
(后置增强)"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />E --> F["返回结果"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" /><bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />%% 样式定义<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style A fill:#e1f5fe,stroke:#01579b,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style B fill:#fff3e0,stroke:#f57c00,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style C fill:#f1f8e9,stroke:#7cb342,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style D fill:#fff8e1,stroke:#ffb300,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style E fill:#fce4ec,stroke:#c2185b,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style F fill:#e8f5e8,stroke:#388e3c,stroke-width:2pxWeb MVC - 前端控制器模式

SpringWind的Web MVC实现了经典的前端控制器模式:
  1. @WebServlet("/*")public class DispatcherServlet extends HttpServlet {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />protected void service(HttpServletRequest req, HttpServletResponse resp) {<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />// 1. 获取请求路径<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />String uri = req.getRequestURI();<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />// 2. 查找处理器<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />HandlerMethod handler = getHandler(uri);<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />// 3. 解析参数<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />Object[] args = resolveArguments(handler, req, resp);<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />// 4. 调用Controller方法<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />Object result = handler.invoke(args);<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />// 5. 处理响应<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />handleResult(result, resp);<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />}}
复制代码
请求处理流程:
graph LR<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />A[HTTP请求] --> B[DispatcherServlet]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />B --> C[URL映射]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />C --> D[参数解析]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />D --> E[调用Controller]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />E --> F{返回类型判断}<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />F -->|返回View名称| G[视图解析]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />F -->|返回数据| H[消息转换]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />G --> I[视图渲染]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />H --> I<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />I --> J[HTTP响应]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" /><bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style A fill:#90EE90,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style B fill:#ADD8E6,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style C fill:#FFB6C1,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style D fill:#DDA0DD,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style E fill:#FFD700,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style F fill:#F0E68C,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style G fill:#87CEEB,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style H fill:#98FB98,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style I fill:#FFA07A,stroke:#333,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style J fill:#90EE90,stroke:#333,stroke-width:2pxJDBC模板 - 样板代码的终结者

JdbcTemplate只是把基础JDBC操作的步骤封装起来,实现起来非常简单,没有ORM框架那么复杂:
  1. public  T queryForObject(String sql, RowMapper mapper, Object... args) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />Connection conn = null;<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />PreparedStatement stmt = null;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />ResultSet rs = null;<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />try {<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />conn = getConnection();<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />// 1. 获取连接<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />stmt = prepareStatement(sql);  // 2. 创建语句<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />setParameters(stmt, args);<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /> // 3. 设置参数<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />rs = stmt.executeQuery();<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />  // 4. 执行查询<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" /><bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" />return mapper.mapRow(rs, 0);   // 5. 映射结果(你只需要关心这一步)<bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />} catch (SQLException e) {<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />throw new RuntimeException(e);<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />} finally {<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" />closeResources(rs, stmt, conn);  // 6. 关闭资源<bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />}}
复制代码
你只需要提供SQL和结果映射逻辑,其他的都由框架处理。
深入理解Spring框架

为什么要用注解?

注解本质上是元数据,用来描述代码的特性。Java通过反射API可以在运行时读取这些注解:
  1. // 扫描类上的注解Class clazz = Class.forName("com.example.UserService");if (clazz.isAnnotationPresent(Service.class)) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// 这是一个Service,注册为Bean}// 扫描字段上的注解for (Field field : clazz.getDeclaredFields()) {<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />if (field.isAnnotationPresent(Autowired.class)) {<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" /><bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />// 这个字段需要依赖注入<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />}}
复制代码
注解相比XML配置的优势:

  • 就近原则:配置和代码在一起,更直观
  • 类型安全:编译期检查,避免拼写错误
  • 重构友好:IDE可以自动重构
反射 - Spring的基石

Spring大量使用反射来实现框架功能:
  1. // 如果目标类实现了接口,目标类实现的接口数量大于0
  2. if (interfaces.length > 0) {
  3.     // 使用JDK动态代理创建代理对象
  4.     return Proxy.newProxyInstance(
  5.         // 指定类加载器,用于加载动态生成的代理类
  6.         classLoader,
  7.         // 代理类需要实现的接口数组,代理对象需要实现接口的所有方法
  8.         interfaces,
  9.         // 创建调用处理器,将目标对象和切面列表传入
  10.         // AopInvocationHandler负责处理方法调用时的切面逻辑
  11.         new AopInvocationHandler(target, aspects)
  12.     );
  13. }
复制代码
反射的性能确实比直接调用慢,但Spring通过缓存来优化:
  1. // 构造器缓存private Map> constructorCache = new ConcurrentHashMap();public Object createBean(Class clazz) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />Constructor constructor = constructorCache.computeIfAbsent(clazz, c -> {<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />return c.getDeclaredConstructor();<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />});<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />return constructor.newInstance();}
复制代码
设计模式 - Spring是经典设计模式的忠实拥趸

Spring框架中应用了大量的设计模式:
设计模式应用场景举例工厂模式Bean的创建ApplicationContext就是Bean工厂单例模式Bean的作用域默认的单例Bean代理模式AOP实现JDK动态代理、CGLIB代理模板方法模式固定流程封装JdbcTemplate、RestTemplate策略模式不同的实现策略RowMapper结果映射观察者模式事件机制BeanPostProcessor前端控制器模式Web MVCDispatcherServlet注册表模式Bean定义管理BeanDefinitionRegistry学习Spring,也是在学习如何优雅地应用设计模式。
并发安全 - ConcurrentHashMap的选择

Spring容器是线程安全的,SpringWind也要保证这一点。我们使用ConcurrentHashMap而不是Hashtable或加锁的HashMap:
  1. // ✓ 推荐:ConcurrentHashMapprivate Map singletonObjects = new ConcurrentHashMap();// ✗ 不推荐:Hashtable(方法级锁,性能差)private Map singletonObjects = new Hashtable();// ✗ 不推荐:synchronized包装(同样是粗粒度锁)private Map singletonObjects =<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />Collections.synchronizedMap(new HashMap());
复制代码
ConcurrentHashMap使用分段锁,并发性能远高于Hashtable。
参照Spring框架设计Springwind的架构

整体架构设计

SpringWind采用分层架构,从下到上分为四层:
  1. ┌─────────────────────────────────────────────────────────────┐│<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" /><bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" /><bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />应用层 (Application Layer)<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />││  开发者编写的业务代码:Controller、Service、DAO、Repository<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />  │└─────────────────────────────────────────────────────────────┘<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" /> ↓┌─────────────────────────────────────────────────────────────┐│<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" /><bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" /><bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />框架层 (Framework Layer)<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" /><bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" />  ││  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  ││  │   Web MVC   │  │<bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" /> AOP<bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" /> │  │   JDBC Template<bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" /> │  ││  └─────────────┘  └─────────────┘  └─────────────────────┘  │└─────────────────────────────────────────────────────────────┘<bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" /><bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" /><bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" /><bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" /><bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" /><bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" /><bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" /> ↓┌─────────────────────────────────────────────────────────────┐│<bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" /><bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" /><bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" /><bean id="userService" >
  119.     <property name="userDao" ref="userDao"/>
  120. </bean>
  121. <bean id="userDao" /> 核心容器层 (Core Container Layer)<bean id="userService" >
  122.     <property name="userDao" ref="userDao"/>
  123. </bean>
  124. <bean id="userDao" /><bean id="userService" >
  125.     <property name="userDao" ref="userDao"/>
  126. </bean>
  127. <bean id="userDao" /><bean id="userService" >
  128.     <property name="userDao" ref="userDao"/>
  129. </bean>
  130. <bean id="userDao" /> ││  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  ││  │ Bean 定义   │  │ 依赖注入<bean id="userService" >
  131.     <property name="userDao" ref="userDao"/>
  132. </bean>
  133. <bean id="userDao" />  │  │ 生命周期管理<bean id="userService" >
  134.     <property name="userDao" ref="userDao"/>
  135. </bean>
  136. <bean id="userDao" /><bean id="userService" >
  137.     <property name="userDao" ref="userDao"/>
  138. </bean>
  139. <bean id="userDao" />  │  ││  │ 管理<bean id="userService" >
  140.     <property name="userDao" ref="userDao"/>
  141. </bean>
  142. <bean id="userDao" /><bean id="userService" >
  143.     <property name="userDao" ref="userDao"/>
  144. </bean>
  145. <bean id="userDao" />│  │<bean id="userService" >
  146.     <property name="userDao" ref="userDao"/>
  147. </bean>
  148. <bean id="userDao" /><bean id="userService" >
  149.     <property name="userDao" ref="userDao"/>
  150. </bean>
  151. <bean id="userDao" /><bean id="userService" >
  152.     <property name="userDao" ref="userDao"/>
  153. </bean>
  154. <bean id="userDao" />  │  │<bean id="userService" >
  155.     <property name="userDao" ref="userDao"/>
  156. </bean>
  157. <bean id="userDao" /><bean id="userService" >
  158.     <property name="userDao" ref="userDao"/>
  159. </bean>
  160. <bean id="userDao" /><bean id="userService" >
  161.     <property name="userDao" ref="userDao"/>
  162. </bean>
  163. <bean id="userDao" /><bean id="userService" >
  164.     <property name="userDao" ref="userDao"/>
  165. </bean>
  166. <bean id="userDao" /><bean id="userService" >
  167.     <property name="userDao" ref="userDao"/>
  168. </bean>
  169. <bean id="userDao" /> │  ││  └─────────────┘  └─────────────┘  └─────────────────────┘  ││  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  ││  │ 单例池<bean id="userService" >
  170.     <property name="userDao" ref="userDao"/>
  171. </bean>
  172. <bean id="userDao" />   │  │ 循环依赖<bean id="userService" >
  173.     <property name="userDao" ref="userDao"/>
  174. </bean>
  175. <bean id="userDao" />  │  │ BeanPost<bean id="userService" >
  176.     <property name="userDao" ref="userDao"/>
  177. </bean>
  178. <bean id="userDao" /><bean id="userService" >
  179.     <property name="userDao" ref="userDao"/>
  180. </bean>
  181. <bean id="userDao" /><bean id="userService" >
  182.     <property name="userDao" ref="userDao"/>
  183. </bean>
  184. <bean id="userDao" />│  ││  │<bean id="userService" >
  185.     <property name="userDao" ref="userDao"/>
  186. </bean>
  187. <bean id="userDao" /><bean id="userService" >
  188.     <property name="userDao" ref="userDao"/>
  189. </bean>
  190. <bean id="userDao" /><bean id="userService" >
  191.     <property name="userDao" ref="userDao"/>
  192. </bean>
  193. <bean id="userDao" /> │  │ 解决<bean id="userService" >
  194.     <property name="userDao" ref="userDao"/>
  195. </bean>
  196. <bean id="userDao" /><bean id="userService" >
  197.     <property name="userDao" ref="userDao"/>
  198. </bean>
  199. <bean id="userDao" /> │  │ Processor<bean id="userService" >
  200.     <property name="userDao" ref="userDao"/>
  201. </bean>
  202. <bean id="userDao" /><bean id="userService" >
  203.     <property name="userDao" ref="userDao"/>
  204. </bean>
  205. <bean id="userDao" />   │  ││  └─────────────┘  └─────────────┘  └─────────────────────┘  │└─────────────────────────────────────────────────────────────┘<bean id="userService" >
  206.     <property name="userDao" ref="userDao"/>
  207. </bean>
  208. <bean id="userDao" /><bean id="userService" >
  209.     <property name="userDao" ref="userDao"/>
  210. </bean>
  211. <bean id="userDao" /><bean id="userService" >
  212.     <property name="userDao" ref="userDao"/>
  213. </bean>
  214. <bean id="userDao" /><bean id="userService" >
  215.     <property name="userDao" ref="userDao"/>
  216. </bean>
  217. <bean id="userDao" /><bean id="userService" >
  218.     <property name="userDao" ref="userDao"/>
  219. </bean>
  220. <bean id="userDao" /><bean id="userService" >
  221.     <property name="userDao" ref="userDao"/>
  222. </bean>
  223. <bean id="userDao" /><bean id="userService" >
  224.     <property name="userDao" ref="userDao"/>
  225. </bean>
  226. <bean id="userDao" /> ↓┌─────────────────────────────────────────────────────────────┐│<bean id="userService" >
  227.     <property name="userDao" ref="userDao"/>
  228. </bean>
  229. <bean id="userDao" /><bean id="userService" >
  230.     <property name="userDao" ref="userDao"/>
  231. </bean>
  232. <bean id="userDao" /><bean id="userService" >
  233.     <property name="userDao" ref="userDao"/>
  234. </bean>
  235. <bean id="userDao" /><bean id="userService" >
  236.     <property name="userDao" ref="userDao"/>
  237. </bean>
  238. <bean id="userDao" />   基础设施层 (Infrastructure Layer)<bean id="userService" >
  239.     <property name="userDao" ref="userDao"/>
  240. </bean>
  241. <bean id="userDao" /><bean id="userService" >
  242.     <property name="userDao" ref="userDao"/>
  243. </bean>
  244. <bean id="userDao" />   ││  反射 API | 类加载器 | 动态代理 | 注解处理 | 并发工具<bean id="userService" >
  245.     <property name="userDao" ref="userDao"/>
  246. </bean>
  247. <bean id="userDao" /><bean id="userService" >
  248.     <property name="userDao" ref="userDao"/>
  249. </bean>
  250. <bean id="userDao" /><bean id="userService" >
  251.     <property name="userDao" ref="userDao"/>
  252. </bean>
  253. <bean id="userDao" /> │└─────────────────────────────────────────────────────────────┘
复制代码
核心模块设计

1. IoC容器模块

核心类: SpringWindApplicationContext
主要职责:

  • 组件扫描和注册
  • Bean的创建和缓存
  • 依赖注入
  • 生命周期管理
  • 循环依赖解决(三级缓存)
关键代码(SpringWindApplicationContext.java):
  1. public class SpringWindApplicationContext {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// Bean定义映射表(使用ConcurrentHashMap提升并发性能)<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private final Map beanDefinitionMap = new ConcurrentHashMap();<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />// 三级缓存机制(解决循环依赖的核心)<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />// 一级缓存:完整初始化的Bean对象(依赖注入完成、初始化方法执行完成)<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />private final Map singletonObjects = new ConcurrentHashMap();<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />// 二级缓存:早期Bean引用(已实例化但未完成依赖注入,可能是代理对象)<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />private final Map earlySingletonObjects = new ConcurrentHashMap();<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />// 三级缓存:ObjectFactory工厂对象(关键!延迟生成早期引用,支持AOP提前代理)<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />private final Map, Constructor> constructorCache = new ConcurrentHashMap();<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />public SpringWindApplicationContext(Class configClass) {<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />scanComponents(configClass);<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />  // 1. 扫描组件<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />createSingletonBeans();<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />   // 2. 创建单例Bean<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />dependencyInjection();<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" /><bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />// 3. 依赖注入<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" />invokeInitMethods();<bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" /><bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" />  // 4. 执行初始化方法(已在getBean中完成,保留兼容)<bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" />}}
复制代码
Bean创建流程核心代码(SpringWindApplicationContext.java的getBean方法):
  1. public Object getBean(String beanName) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// 1. 首先从一级缓存获取完全初始化好的Bean<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />Object bean = singletonObjects.get(beanName);<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />if (bean != null) {<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />return bean;<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />}<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />// 2. 检查循环依赖:如果当前Bean正在创建中<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />if (singletonsCurrentlyInCreation.contains(beanName)) {<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />// 先从二级缓存获取早期对象<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />bean = earlySingletonObjects.get(beanName);<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />if (bean != null) {<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />return bean;<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />}<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />// 如果二级缓存没有,尝试从三级缓存获取ObjectFactory<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" /><bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" />ObjectFactory factory = singletonFactories.get(beanName);<bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />if (factory != null) {<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" /><bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" />// 调用ObjectFactory获取早期对象,并放入二级缓存<bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" /><bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" /><bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" />bean = factory.getObject();  // 此处关键!可能创建AOP代理<bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" /><bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" /><bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" />earlySingletonObjects.put(beanName, bean);<bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" /><bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" /><bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" />singletonFactories.remove(beanName);<bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" /><bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" /><bean id="userService" >
  119.     <property name="userDao" ref="userDao"/>
  120. </bean>
  121. <bean id="userDao" />return bean;<bean id="userService" >
  122.     <property name="userDao" ref="userDao"/>
  123. </bean>
  124. <bean id="userDao" /><bean id="userService" >
  125.     <property name="userDao" ref="userDao"/>
  126. </bean>
  127. <bean id="userDao" />}<bean id="userService" >
  128.     <property name="userDao" ref="userDao"/>
  129. </bean>
  130. <bean id="userDao" />}<bean id="userService" >
  131.     <property name="userDao" ref="userDao"/>
  132. </bean>
  133. <bean id="userDao" />// 3. 标记为正在创建<bean id="userService" >
  134.     <property name="userDao" ref="userDao"/>
  135. </bean>
  136. <bean id="userDao" />singletonsCurrentlyInCreation.add(beanName);<bean id="userService" >
  137.     <property name="userDao" ref="userDao"/>
  138. </bean>
  139. <bean id="userDao" />try {<bean id="userService" >
  140.     <property name="userDao" ref="userDao"/>
  141. </bean>
  142. <bean id="userDao" /><bean id="userService" >
  143.     <property name="userDao" ref="userDao"/>
  144. </bean>
  145. <bean id="userDao" />// 4. 实例化<bean id="userService" >
  146.     <property name="userDao" ref="userDao"/>
  147. </bean>
  148. <bean id="userDao" /><bean id="userService" >
  149.     <property name="userDao" ref="userDao"/>
  150. </bean>
  151. <bean id="userDao" />bean = createBeanInstance(beanDefinition.getBeanClass());<bean id="userService" >
  152.     <property name="userDao" ref="userDao"/>
  153. </bean>
  154. <bean id="userDao" /><bean id="userService" >
  155.     <property name="userDao" ref="userDao"/>
  156. </bean>
  157. <bean id="userDao" />// 5. 放入三级缓存(ObjectFactory,支持AOP提前创建代理)<bean id="userService" >
  158.     <property name="userDao" ref="userDao"/>
  159. </bean>
  160. <bean id="userDao" /><bean id="userService" >
  161.     <property name="userDao" ref="userDao"/>
  162. </bean>
  163. <bean id="userDao" />final Object rawBean = bean;<bean id="userService" >
  164.     <property name="userDao" ref="userDao"/>
  165. </bean>
  166. <bean id="userDao" /><bean id="userService" >
  167.     <property name="userDao" ref="userDao"/>
  168. </bean>
  169. <bean id="userDao" />singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, rawBean));<bean id="userService" >
  170.     <property name="userDao" ref="userDao"/>
  171. </bean>
  172. <bean id="userDao" /><bean id="userService" >
  173.     <property name="userDao" ref="userDao"/>
  174. </bean>
  175. <bean id="userDao" />// 6. 依赖注入(可能触发循环依赖)<bean id="userService" >
  176.     <property name="userDao" ref="userDao"/>
  177. </bean>
  178. <bean id="userDao" /><bean id="userService" >
  179.     <property name="userDao" ref="userDao"/>
  180. </bean>
  181. <bean id="userDao" />doDependencyInjection(bean);<bean id="userService" >
  182.     <property name="userDao" ref="userDao"/>
  183. </bean>
  184. <bean id="userDao" /><bean id="userService" >
  185.     <property name="userDao" ref="userDao"/>
  186. </bean>
  187. <bean id="userDao" />// 7. 前置处理器<bean id="userService" >
  188.     <property name="userDao" ref="userDao"/>
  189. </bean>
  190. <bean id="userDao" /><bean id="userService" >
  191.     <property name="userDao" ref="userDao"/>
  192. </bean>
  193. <bean id="userDao" />bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);<bean id="userService" >
  194.     <property name="userDao" ref="userDao"/>
  195. </bean>
  196. <bean id="userDao" /><bean id="userService" >
  197.     <property name="userDao" ref="userDao"/>
  198. </bean>
  199. <bean id="userDao" />// 8. @PostConstruct初始化方法<bean id="userService" >
  200.     <property name="userDao" ref="userDao"/>
  201. </bean>
  202. <bean id="userDao" /><bean id="userService" >
  203.     <property name="userDao" ref="userDao"/>
  204. </bean>
  205. <bean id="userDao" />if (beanDefinition.getInitMethod() != null) {<bean id="userService" >
  206.     <property name="userDao" ref="userDao"/>
  207. </bean>
  208. <bean id="userDao" /><bean id="userService" >
  209.     <property name="userDao" ref="userDao"/>
  210. </bean>
  211. <bean id="userDao" /><bean id="userService" >
  212.     <property name="userDao" ref="userDao"/>
  213. </bean>
  214. <bean id="userDao" />beanDefinition.getInitMethod().invoke(bean);<bean id="userService" >
  215.     <property name="userDao" ref="userDao"/>
  216. </bean>
  217. <bean id="userDao" /><bean id="userService" >
  218.     <property name="userDao" ref="userDao"/>
  219. </bean>
  220. <bean id="userDao" />}<bean id="userService" >
  221.     <property name="userDao" ref="userDao"/>
  222. </bean>
  223. <bean id="userDao" /><bean id="userService" >
  224.     <property name="userDao" ref="userDao"/>
  225. </bean>
  226. <bean id="userDao" />// 9. 后置处理器(AOP通常在这里发生)<bean id="userService" >
  227.     <property name="userDao" ref="userDao"/>
  228. </bean>
  229. <bean id="userDao" /><bean id="userService" >
  230.     <property name="userDao" ref="userDao"/>
  231. </bean>
  232. <bean id="userDao" />bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);<bean id="userService" >
  233.     <property name="userDao" ref="userDao"/>
  234. </bean>
  235. <bean id="userDao" /><bean id="userService" >
  236.     <property name="userDao" ref="userDao"/>
  237. </bean>
  238. <bean id="userDao" />// 10. 放入一级缓存(完全初始化好的Bean)<bean id="userService" >
  239.     <property name="userDao" ref="userDao"/>
  240. </bean>
  241. <bean id="userDao" /><bean id="userService" >
  242.     <property name="userDao" ref="userDao"/>
  243. </bean>
  244. <bean id="userDao" />singletonObjects.put(beanName, bean);<bean id="userService" >
  245.     <property name="userDao" ref="userDao"/>
  246. </bean>
  247. <bean id="userDao" /><bean id="userService" >
  248.     <property name="userDao" ref="userDao"/>
  249. </bean>
  250. <bean id="userDao" />// 11. 清理二级缓存和三级缓存<bean id="userService" >
  251.     <property name="userDao" ref="userDao"/>
  252. </bean>
  253. <bean id="userDao" /><bean id="userService" >
  254.     <property name="userDao" ref="userDao"/>
  255. </bean>
  256. <bean id="userDao" />earlySingletonObjects.remove(beanName);<bean id="userService" >
  257.     <property name="userDao" ref="userDao"/>
  258. </bean>
  259. <bean id="userDao" /><bean id="userService" >
  260.     <property name="userDao" ref="userDao"/>
  261. </bean>
  262. <bean id="userDao" />singletonFactories.remove(beanName);<bean id="userService" >
  263.     <property name="userDao" ref="userDao"/>
  264. </bean>
  265. <bean id="userDao" /><bean id="userService" >
  266.     <property name="userDao" ref="userDao"/>
  267. </bean>
  268. <bean id="userDao" />return bean;<bean id="userService" >
  269.     <property name="userDao" ref="userDao"/>
  270. </bean>
  271. <bean id="userDao" />} finally {<bean id="userService" >
  272.     <property name="userDao" ref="userDao"/>
  273. </bean>
  274. <bean id="userDao" /><bean id="userService" >
  275.     <property name="userDao" ref="userDao"/>
  276. </bean>
  277. <bean id="userDao" />// 12. 从正在创建集合中移除<bean id="userService" >
  278.     <property name="userDao" ref="userDao"/>
  279. </bean>
  280. <bean id="userDao" /><bean id="userService" >
  281.     <property name="userDao" ref="userDao"/>
  282. </bean>
  283. <bean id="userDao" />singletonsCurrentlyInCreation.remove(beanName);<bean id="userService" >
  284.     <property name="userDao" ref="userDao"/>
  285. </bean>
  286. <bean id="userDao" />}}
复制代码
关键点

  • 步骤5:放入的是ObjectFactory,而不是Bean本身,这是三级缓存的精髓
  • 步骤6:依赖注入时可能触发循环依赖,会走步骤2的逻辑
  • 步骤9:如果在getEarlyBeanReference中已创建代理,这里会检测并跳过
2. AOP模块

核心类: AspectProcessor、SmartInstantiationAwareBeanPostProcessor、AopInvocationHandler、AopMethodInterceptor
主要职责:

  • 切面注册和管理
  • 代理对象创建(JDK动态代理/CGLIB字节码增强)
  • 切点匹配和通知执行
  • 早期代理创建(通过SmartInstantiationAwareBeanPostProcessor解决循环依赖+AOP的组合问题)
关键设计:AspectProcessor实现SmartInstantiationAwareBeanPostProcessor接口
这是解决"循环依赖+AOP"场景的核心设计:
  1. public class AspectProcessor implements SmartInstantiationAwareBeanPostProcessor {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// 在Bean早期引用被获取时调用(循环依赖场景)<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />@Override<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />public Object getEarlyBeanReference(Object bean, String beanName) {<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />// 如果Bean需要AOP代理,在这里提前创建<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />if (shouldProxy(bean)) {<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />return createProxy(bean);  // 创建代理对象<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />}<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />return bean;  // 不需要代理,返回原始对象<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />}<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />// 在Bean初始化后调用(正常场景)<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />@Override<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" />public Object postProcessAfterInitialization(Object bean, String beanName) {<bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" /><bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" />// 如果已经在getEarlyBeanReference中创建了代理,这里跳过<bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" /><bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />if (已经创建过代理) {<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />return bean;<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" />}<bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" /><bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" />// 否则在这里创建代理<bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" /><bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" />if (shouldProxy(bean)) {<bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" /><bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" /><bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" />return createProxy(bean);<bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" /><bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" />}<bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" /><bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" />return bean;<bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" />}}
复制代码
工作原理:

  • 正常场景(无循环依赖):

    • getEarlyBeanReference不会被调用
    • 在postProcessAfterInitialization中创建AOP代理

  • 循环依赖场景

    • 当Bean A被Bean B依赖时,会触发ObjectFactory.getObject()
    • getObject()内部调用getEarlyBeanReference(beanA)
    • 在getEarlyBeanReference中提前创建AOP代理
    • 代理对象被放入二级缓存,B获取到的是代理
    • 后续postProcessAfterInitialization检测到已创建代理,跳过

为什么需要这个机制?

  • 如果不在getEarlyBeanReference中创建代理,B获取到的是原始对象
  • 后续在postProcessAfterInitialization创建代理后,A持有的是代理对象,但B持有的仍是原始对象
  • 导致同一个Bean存在两个不同的对象,违反了单例原则
通过SmartInstantiationAwareBeanPostProcessor,确保:

  • 循环依赖的所有Bean获取到同一个代理对象
  • 不会产生多个不同的代理或原始对象
代理创建逻辑(AspectProcessor.java):
  1. public Object createProxy(Object target) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />List matchedAspects = findMatchedAspects(target.getClass());<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />if (matchedAspects.isEmpty()) {<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" /><bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />return target;  // 没有切面,返回原始对象<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />}<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />// 如果实现了接口,使用JDK动态代理<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />Class[] interfaces = target.getClass().getInterfaces();<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />if (interfaces.length > 0) {<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />return Proxy.newProxyInstance(<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />target.getClass().getClassLoader(),<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />interfaces,<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" /><bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />new AopInvocationHandler(target, matchedAspects)<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />);<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />}<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" />// 否则使用CGLIB代理<bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" />Enhancer enhancer = new Enhancer();<bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />enhancer.setSuperclass(target.getClass());<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" />enhancer.setCallback(new AopMethodInterceptor(target, matchedAspects));<bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" />return enhancer.create();}
复制代码
3. Web MVC模块

核心类: DispatcherServlet、HandlerMapping、PathMatcher
主要职责:

  • 请求路由
  • 参数解析和绑定
  • Controller调用
  • 视图解析
请求处理流程:
---title: Spring MVC 请求处理流程---flowchart LR<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />A["HTTP请求"] --> B["DispatcherServlet
前端控制器"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />B --> C["HandlerMapping
处理器映射"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />C --> D["athMatcher
路径匹配器"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />D --> E["参数解析器
@PathVariable
@RequestParam
@RequestBody"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />E --> F["Controller方法
业务逻辑处理"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />F --> G["结果处理器
JSON/视图转换"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />G --> H["HTTP响应"]<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" /><bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />%% 样式定义<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style A fill:#e3f2fd,stroke:#1565c0,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style B fill:#e8f5e8,stroke:#388e3c,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style C fill:#fff3e0,stroke:#f57c00,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style D fill:#fce4ec,stroke:#c2185b,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style E fill:#e1f5fe,stroke:#01579b,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style F fill:#fff8e1,stroke:#ffb300,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style G fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px<bean id="userService" >
    <property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" />style H fill:#e8f5e8,stroke:#388e3c,stroke-width:2px4. JDBC模块

核心类: JdbcTemplate、RowMapper
主要职责:

  • 连接管理
  • SQL执行
  • 结果集映射
  • 资源关闭
模板方法实现:
  1. public  List query(String sql, RowMapper mapper, Object... args) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />Connection conn = null;<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />PreparedStatement stmt = null;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />ResultSet rs = null;<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />try {<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />conn = getConnection();<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />// 固定步骤1<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />stmt = prepareStatement(sql);  // 固定步骤2<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />setParameters(stmt, args);<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /> // 固定步骤3<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />rs = stmt.executeQuery();<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />  // 固定步骤4<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" /><bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" />return mapResults(rs, mapper); // 可变步骤(回调)<bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />} catch (SQLException e) {<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />throw new RuntimeException(e);<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />} finally {<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" />closeResources(rs, stmt, conn); // 固定步骤5<bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />}}
复制代码
注解体系设计

SpringWind定义了一套完整的注解体系(共21个注解):
IoC/DI 注解:
注解作用元注解@Component通用组件-@Service服务层组件@Component@Controller控制器组件@Component@Repository数据访问层组件@Component@Configuration配置类@Component@Autowired依赖注入-@Bean方法级Bean定义-生命周期注解:
注解作用来源@PostConstructBean 初始化方法javax.annotation@PreDestroyBean 销毁方法javax.annotationWeb MVC 注解:
注解作用说明@RequestMappingURL映射(通用)支持所有HTTP方法@GetMappingGET请求映射快捷注解@PostMappingPOST请求映射快捷注解@PutMappingPUT请求映射快捷注解@DeleteMappingDELETE请求映射快捷注解@PathVariable路径变量绑定如 /user/{id}@RequestParam请求参数绑定如 ?name=xxx@RequestBody请求体绑定(JSON)自动反序列化@ResponseBody响应体(JSON)自动序列化AOP 注解:
注解作用通知类型@Aspect标记切面类-@Before前置通知方法执行前@After后置通知方法执行后@Around环绕通知完全控制方法执行事务注解:
注解作用状态@Transactional声明式事务需配合AOP实现性能优化策略

1. 构造器缓存

反射获取构造器的成本较高,缓存起来:
  1. private final Map> constructorCache = new ConcurrentHashMap();public Object createBean(Class clazz) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />Constructor constructor = constructorCache.computeIfAbsent(clazz, c -> {<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />try {<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />return c.getDeclaredConstructor();<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />} catch (NoSuchMethodException e) {<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />throw new BeanCreationException("找不到无参构造器", e);<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />}<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />});<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />return constructor.newInstance();}
复制代码
2. 切点表达式缓存

正则表达式编译很慢,缓存编译后的Pattern:
  1. private final Map patternCache = new ConcurrentHashMap();public boolean matches(String pointcut, String methodName) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />Pattern pattern = patternCache.computeIfAbsent(pointcut, p -> {<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />String regex = pointcut.replace("*", ".*").replace(".", "\\.");<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />return Pattern.compile(regex);<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />});<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />return pattern.matcher(methodName).matches();}
复制代码
3. 使用ConcurrentHashMap

所有需要并发访问的Map都使用ConcurrentHashMap,避免锁竞争。
SpringWind 与 Spring MVC 的对比

了解 SpringWind 与 Spring MVC 的异同,可以帮助你更好地理解框架的设计取舍。
功能对比表

功能特性SpringWindSpring MVC说明IoC 容器✅ 基本实现✅ 完整实现 + 复杂场景SpringWind 实现了单例 Bean 管理、依赖注入、生命周期管理依赖注入✅ 字段注入、方法注入✅ 字段、方法、构造器注入SpringWind 暂不支持构造器注入循环依赖解决✅ 三级缓存 + SmartInstantiationAwareBeanPostProcessor✅ 三级缓存 + 多种策略SpringWind 核心机制与 Spring 相同,都支持早期代理创建BeanPostProcessor✅ 基本实现✅ 完整实现 + 多种类型SpringWind 支持前置和后置处理SmartInstantiation
AwareBeanPostProcessor
✅ 支持✅ 完整支持SpringWind 支持在 Bean 实例化早期创建代理,解决循环依赖Bean 作用域⚠️ 仅单例(Singleton)✅ Singleton、Prototype、Request、Session 等SpringWind 只支持单例模式AOP 支持✅ JDK/CGLIB 代理 + 早期代理✅ AspectJ 集成 + 更强大的切点表达式SpringWind 实现了基本的 AOP 功能,支持早期代理创建切面类型✅ @Before、@After、@Around✅ @Before、@After、@Around、@AfterReturning、@AfterThrowingSpringWind 支持三种基本通知类型Web MVC✅ 基本实现✅ 完整的 MVC 栈 + 异步支持SpringWind 实现了核心的请求映射和参数绑定请求映射✅ @RequestMapping✅ @RequestMapping、@GetMapping、@PostMapping 等SpringWind 使用统一的 @RequestMapping参数绑定✅ @PathVariable、@RequestParam、@RequestBody✅ 更多参数类型和转换器SpringWind 支持基本的参数绑定JSON 响应✅ 自动序列化✅ 多种视图解析器SpringWind 使用 Jackson 进行 JSON 序列化JDBC 支持✅ JdbcTemplate✅ JdbcTemplate + JPA/Hibernate 集成SpringWind 实现了 JdbcTemplate 的核心功能生命周期回调✅ @PostConstruct、@PreDestroy✅ @PostConstruct、@PreDestroy、InitializingBean、DisposableBeanSpringWind 支持标准的生命周期回调事务管理❌ 需自行实现✅ 声明式和编程式事务SpringWind 暂不支持,可通过 AOP 自己实现配置方式✅ 注解驱动✅ 注解 + XML + Java ConfigSpringWind 主要使用注解配置国际化(i18n)❌ 不支持✅ MessageSourceSpring 提供完整的国际化支持事件机制❌ 不支持✅ ApplicationEventSpring 提供事件发布和监听机制SpEL 表达式❌ 不支持✅ 完整的表达式语言Spring 支持强大的 SpEL 表达式代码量~5000 行~50 万行SpringWind 代码量相对较小,易于理解学习难度⭐⭐ 容易⭐⭐⭐⭐ 较难SpringWind 适合初学者理解原理生产就绪✅ 教学/小项目✅ 企业级应用Spring 经过大规模生产验证使用场景对比

场景推荐使用原因学习 Spring 原理SpringWind代码简洁,易于理解核心机制企业级应用Spring MVC功能完整,生产就绪小型工具项目SpringWind轻量级,快速启动Demo/原型开发SpringWind简单直接,无需复杂配置大型分布式系统Spring Boot/Cloud完整的生态系统和中间件支持需要事务支持Spring MVCSpringWind 需要自己实现事务需要复杂 AOPSpring MVC支持 AspectJ 和复杂切点表达式快速原型验证SpringWind启动快,依赖少应用代码对比示例

定义一个简单的 Controller:
  1. // SpringWind 和 Spring MVC 的代码几乎完全相同@Controller@RequestMapping("/user")public class UserController {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@Autowired<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private UserService userService;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />@RequestMapping("/list")<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />@ResponseBody<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />public List list() {<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />return userService.getAllUsers();<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />}<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />@RequestMapping("/get")<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />@ResponseBody<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />public User getUser(@RequestParam("id") Long id) {<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />return userService.getUserById(id);<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />}<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />@RequestMapping("/create")<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />@ResponseBody<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />public User createUser(@RequestBody User user) {<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />return userService.createUser(user);<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" />}}
复制代码
启动应用:
  1. // SpringWindpublic class Application {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />public static void main(String[] args) {<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />// 启动SpringWind应用<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />SpringWindApplication app = SpringWindApplication.run(WebDemoApplication.class, args);<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />// 启动 Tomcat<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />TomcatServer.start(app.getContext());<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />}}// Spring Boot@SpringBootApplicationpublic class Application {<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />public static void main(String[] args) {<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />SpringApplication.run(Application.class, args);<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />}}
复制代码
迁移成本

从 SpringWind 迁移到 Spring MVC:

  • 难度:⭐⭐ 容易
  • 工作量:主要是替换依赖和配置
  • 代码改动:业务代码几乎不需要改动
  • 注意事项

    • 添加 Spring Boot Starter 依赖
    • 调整配置文件(application.yml/properties)
    • 构造器注入需要添加构造器
    • 事务注解需要启用 @EnableTransactionManagement

性能对比

指标SpringWindSpring MVC启动时间~200ms~2-5s(Spring Boot)内存占用~50MB~150-300MB依赖数量~5 个~50-100 个jar 包大小~2MB~20-50MB并发性能良好优秀注意:SpringWind 的性能优势主要体现在轻量级场景,没有深入优化高并发,对于大型应用,Spring 的优化更加全面。
学习建议


  • 先学 SpringWind,再学 Spring

    • SpringWind 代码量小,容易看懂核心原理
    • 理解了原理后,再看 Spring 源码会轻松很多

  • 对比学习

    • 用 SpringWind 写一个小项目
    • 用 Spring Boot 实现同样的功能
    • 对比两者的实现差异

  • 渐进式学习

    • IoC/DI → AOP → MVC → JDBC → 事务
    • 每个模块都先在 SpringWind 中理解,再看 Spring 的实现

Springwind框架有什么用

SpringWind不是为了替代Spring,而是为了学习Spring,掌握Spring。但它也有自己的价值:
1. 彻底搞懂Spring原理和运行机制

面试常问的问题,SpringWind都有答案:

  • IoC容器是怎么工作的?
    看SpringWindApplicationContext的实现,200多行代码就能看懂。
  • 循环依赖怎么解决的?
    看三级缓存的实现,代码简洁明了。
  • AOP是怎么实现的?
    看AspectProcessor如何创建代理对象。
  • @Autowired是怎么注入的?
    看dependencyInjection方法,反射设置字段值。
  • DispatcherServlet是怎么分发请求的?
    看Web MVC模块,前端控制器模式的经典实现。
学习建议:

  • 先跑一遍示例项目,看看效果
  • 打断点调试,看Bean是怎么创建的
  • 对照Spring源码,理解设计思想
  • 自己动手改代码,加功能
2. 用在小项目上快速开发

Spring确实有点重,一个简单的Web项目,引入Spring Boot全家桶可能有上百个依赖。
SpringWind只有几个核心依赖:
  1. <bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" /><bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />jakarta.servlet<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />jakarta.servlet-api<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />cglib<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />cglib<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />org.slf4j<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />slf4j-api<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" />
复制代码
适用场景:

  • 小型Web应用
  • 内部工具系统
  • 学习项目
  • Demo演示
3. 探索新功能,给Spring提建议

SpringWind是一个试验田,你可以:

  • 尝试新的设计思路
  • 验证性能优化方案
  • 实现Spring没有的功能
  • 给Spring社区提PR
比如,你可以尝试:

  • 实现响应式编程支持
  • 优化Bean创建性能
  • 简化配置方式
  • 增强AOP功能
Springwind的项目结构

SpringWind的代码组织清晰,模块划分明确:
  1. springwind/├── pom.xml<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" /><bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" /><bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />  # Maven配置├── README.md<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" /><bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /># 项目文档├── src/│   ├── main/│   │   └── java/com/github/microwind/springwind/│   │<bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />   ├── SpringWindApplication.java<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" />  # 框架启动类│   │<bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />   ││   │<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />   ├── annotation/<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" /><bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" /> # 注解定义(13个核心注解)│   │<bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" />   │   ├── Component.java<bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" /><bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" /><bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" />  # 通用组件│   │<bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" />   │   ├── Service.java<bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" /><bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" /><bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" /><bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" /># 服务层│   │<bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" />   │   ├── Controller.java<bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" /><bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" /><bean id="userService" >
  119.     <property name="userDao" ref="userDao"/>
  120. </bean>
  121. <bean id="userDao" /> # 控制器│   │<bean id="userService" >
  122.     <property name="userDao" ref="userDao"/>
  123. </bean>
  124. <bean id="userDao" />   │   ├── Repository.java<bean id="userService" >
  125.     <property name="userDao" ref="userDao"/>
  126. </bean>
  127. <bean id="userDao" /><bean id="userService" >
  128.     <property name="userDao" ref="userDao"/>
  129. </bean>
  130. <bean id="userDao" /><bean id="userService" >
  131.     <property name="userDao" ref="userDao"/>
  132. </bean>
  133. <bean id="userDao" /> # 数据访问层│   │<bean id="userService" >
  134.     <property name="userDao" ref="userDao"/>
  135. </bean>
  136. <bean id="userDao" />   │   ├── Autowired.java<bean id="userService" >
  137.     <property name="userDao" ref="userDao"/>
  138. </bean>
  139. <bean id="userDao" /><bean id="userService" >
  140.     <property name="userDao" ref="userDao"/>
  141. </bean>
  142. <bean id="userDao" /><bean id="userService" >
  143.     <property name="userDao" ref="userDao"/>
  144. </bean>
  145. <bean id="userDao" />  # 依赖注入│   │<bean id="userService" >
  146.     <property name="userDao" ref="userDao"/>
  147. </bean>
  148. <bean id="userDao" />   │   ├── RequestMapping.java<bean id="userService" >
  149.     <property name="userDao" ref="userDao"/>
  150. </bean>
  151. <bean id="userDao" /><bean id="userService" >
  152.     <property name="userDao" ref="userDao"/>
  153. </bean>
  154. <bean id="userDao" /> # URL映射│   │<bean id="userService" >
  155.     <property name="userDao" ref="userDao"/>
  156. </bean>
  157. <bean id="userDao" />   │   ├── PathVariable.java<bean id="userService" >
  158.     <property name="userDao" ref="userDao"/>
  159. </bean>
  160. <bean id="userDao" /><bean id="userService" >
  161.     <property name="userDao" ref="userDao"/>
  162. </bean>
  163. <bean id="userDao" />   # 路径变量│   │<bean id="userService" >
  164.     <property name="userDao" ref="userDao"/>
  165. </bean>
  166. <bean id="userDao" />   │   ├── RequestParam.java<bean id="userService" >
  167.     <property name="userDao" ref="userDao"/>
  168. </bean>
  169. <bean id="userDao" /><bean id="userService" >
  170.     <property name="userDao" ref="userDao"/>
  171. </bean>
  172. <bean id="userDao" />   # 请求参数│   │<bean id="userService" >
  173.     <property name="userDao" ref="userDao"/>
  174. </bean>
  175. <bean id="userDao" />   │   ├── RequestBody.java<bean id="userService" >
  176.     <property name="userDao" ref="userDao"/>
  177. </bean>
  178. <bean id="userDao" /><bean id="userService" >
  179.     <property name="userDao" ref="userDao"/>
  180. </bean>
  181. <bean id="userDao" /><bean id="userService" >
  182.     <property name="userDao" ref="userDao"/>
  183. </bean>
  184. <bean id="userDao" /># 请求体│   │<bean id="userService" >
  185.     <property name="userDao" ref="userDao"/>
  186. </bean>
  187. <bean id="userDao" />   │   ├── Aspect.java<bean id="userService" >
  188.     <property name="userDao" ref="userDao"/>
  189. </bean>
  190. <bean id="userDao" /><bean id="userService" >
  191.     <property name="userDao" ref="userDao"/>
  192. </bean>
  193. <bean id="userDao" /><bean id="userService" >
  194.     <property name="userDao" ref="userDao"/>
  195. </bean>
  196. <bean id="userDao" /><bean id="userService" >
  197.     <property name="userDao" ref="userDao"/>
  198. </bean>
  199. <bean id="userDao" /> # 切面│   │<bean id="userService" >
  200.     <property name="userDao" ref="userDao"/>
  201. </bean>
  202. <bean id="userDao" />   │   ├── Before.java<bean id="userService" >
  203.     <property name="userDao" ref="userDao"/>
  204. </bean>
  205. <bean id="userDao" /><bean id="userService" >
  206.     <property name="userDao" ref="userDao"/>
  207. </bean>
  208. <bean id="userDao" /><bean id="userService" >
  209.     <property name="userDao" ref="userDao"/>
  210. </bean>
  211. <bean id="userDao" /><bean id="userService" >
  212.     <property name="userDao" ref="userDao"/>
  213. </bean>
  214. <bean id="userDao" /> # 前置通知│   │<bean id="userService" >
  215.     <property name="userDao" ref="userDao"/>
  216. </bean>
  217. <bean id="userDao" />   │   ├── After.java<bean id="userService" >
  218.     <property name="userDao" ref="userDao"/>
  219. </bean>
  220. <bean id="userDao" /><bean id="userService" >
  221.     <property name="userDao" ref="userDao"/>
  222. </bean>
  223. <bean id="userDao" /><bean id="userService" >
  224.     <property name="userDao" ref="userDao"/>
  225. </bean>
  226. <bean id="userDao" /><bean id="userService" >
  227.     <property name="userDao" ref="userDao"/>
  228. </bean>
  229. <bean id="userDao" />  # 后置通知│   │<bean id="userService" >
  230.     <property name="userDao" ref="userDao"/>
  231. </bean>
  232. <bean id="userDao" />   │   └── Around.java<bean id="userService" >
  233.     <property name="userDao" ref="userDao"/>
  234. </bean>
  235. <bean id="userDao" /><bean id="userService" >
  236.     <property name="userDao" ref="userDao"/>
  237. </bean>
  238. <bean id="userDao" /><bean id="userService" >
  239.     <property name="userDao" ref="userDao"/>
  240. </bean>
  241. <bean id="userDao" /><bean id="userService" >
  242.     <property name="userDao" ref="userDao"/>
  243. </bean>
  244. <bean id="userDao" /> # 环绕通知│   │<bean id="userService" >
  245.     <property name="userDao" ref="userDao"/>
  246. </bean>
  247. <bean id="userDao" />   ││   │<bean id="userService" >
  248.     <property name="userDao" ref="userDao"/>
  249. </bean>
  250. <bean id="userDao" />   ├── core/<bean id="userService" >
  251.     <property name="userDao" ref="userDao"/>
  252. </bean>
  253. <bean id="userDao" /><bean id="userService" >
  254.     <property name="userDao" ref="userDao"/>
  255. </bean>
  256. <bean id="userDao" /><bean id="userService" >
  257.     <property name="userDao" ref="userDao"/>
  258. </bean>
  259. <bean id="userDao" /><bean id="userService" >
  260.     <property name="userDao" ref="userDao"/>
  261. </bean>
  262. <bean id="userDao" /><bean id="userService" >
  263.     <property name="userDao" ref="userDao"/>
  264. </bean>
  265. <bean id="userDao" /><bean id="userService" >
  266.     <property name="userDao" ref="userDao"/>
  267. </bean>
  268. <bean id="userDao" />   # 核心IoC容器│   │<bean id="userService" >
  269.     <property name="userDao" ref="userDao"/>
  270. </bean>
  271. <bean id="userDao" />   │   ├── SpringWindApplicationContext.java  # IoC容器核心│   │<bean id="userService" >
  272.     <property name="userDao" ref="userDao"/>
  273. </bean>
  274. <bean id="userDao" />   │   ├── BeanDefinition.java<bean id="userService" >
  275.     <property name="userDao" ref="userDao"/>
  276. </bean>
  277. <bean id="userDao" /><bean id="userService" >
  278.     <property name="userDao" ref="userDao"/>
  279. </bean>
  280. <bean id="userDao" /> # Bean定义│   │<bean id="userService" >
  281.     <property name="userDao" ref="userDao"/>
  282. </bean>
  283. <bean id="userDao" />   │   ├── BeanPostProcessor.java<bean id="userService" >
  284.     <property name="userDao" ref="userDao"/>
  285. </bean>
  286. <bean id="userDao" />  # Bean后处理器│   │<bean id="userService" >
  287.     <property name="userDao" ref="userDao"/>
  288. </bean>
  289. <bean id="userDao" />   │   └── PropertyValue.java<bean id="userService" >
  290.     <property name="userDao" ref="userDao"/>
  291. </bean>
  292. <bean id="userDao" /><bean id="userService" >
  293.     <property name="userDao" ref="userDao"/>
  294. </bean>
  295. <bean id="userDao" />  # 属性值│   │<bean id="userService" >
  296.     <property name="userDao" ref="userDao"/>
  297. </bean>
  298. <bean id="userDao" />   ││   │<bean id="userService" >
  299.     <property name="userDao" ref="userDao"/>
  300. </bean>
  301. <bean id="userDao" />   ├── aop/<bean id="userService" >
  302.     <property name="userDao" ref="userDao"/>
  303. </bean>
  304. <bean id="userDao" /><bean id="userService" >
  305.     <property name="userDao" ref="userDao"/>
  306. </bean>
  307. <bean id="userDao" /><bean id="userService" >
  308.     <property name="userDao" ref="userDao"/>
  309. </bean>
  310. <bean id="userDao" /><bean id="userService" >
  311.     <property name="userDao" ref="userDao"/>
  312. </bean>
  313. <bean id="userDao" /><bean id="userService" >
  314.     <property name="userDao" ref="userDao"/>
  315. </bean>
  316. <bean id="userDao" /><bean id="userService" >
  317.     <property name="userDao" ref="userDao"/>
  318. </bean>
  319. <bean id="userDao" /><bean id="userService" >
  320.     <property name="userDao" ref="userDao"/>
  321. </bean>
  322. <bean id="userDao" /># AOP实现│   │<bean id="userService" >
  323.     <property name="userDao" ref="userDao"/>
  324. </bean>
  325. <bean id="userDao" />   │   ├── AspectProcessor.java<bean id="userService" >
  326.     <property name="userDao" ref="userDao"/>
  327. </bean>
  328. <bean id="userDao" /><bean id="userService" >
  329.     <property name="userDao" ref="userDao"/>
  330. </bean>
  331. <bean id="userDao" /># 切面处理器│   │<bean id="userService" >
  332.     <property name="userDao" ref="userDao"/>
  333. </bean>
  334. <bean id="userDao" />   │   ├── AspectInfo.java<bean id="userService" >
  335.     <property name="userDao" ref="userDao"/>
  336. </bean>
  337. <bean id="userDao" /><bean id="userService" >
  338.     <property name="userDao" ref="userDao"/>
  339. </bean>
  340. <bean id="userDao" /><bean id="userService" >
  341.     <property name="userDao" ref="userDao"/>
  342. </bean>
  343. <bean id="userDao" /> # 切面信息│   │<bean id="userService" >
  344.     <property name="userDao" ref="userDao"/>
  345. </bean>
  346. <bean id="userDao" />   │   ├── AspectType.java<bean id="userService" >
  347.     <property name="userDao" ref="userDao"/>
  348. </bean>
  349. <bean id="userDao" /><bean id="userService" >
  350.     <property name="userDao" ref="userDao"/>
  351. </bean>
  352. <bean id="userDao" /><bean id="userService" >
  353.     <property name="userDao" ref="userDao"/>
  354. </bean>
  355. <bean id="userDao" /> # 通知类型│   │<bean id="userService" >
  356.     <property name="userDao" ref="userDao"/>
  357. </bean>
  358. <bean id="userDao" />   │   └── AopInvocationHandler.java   # AOP调用处理器│   │<bean id="userService" >
  359.     <property name="userDao" ref="userDao"/>
  360. </bean>
  361. <bean id="userDao" />   ││   │<bean id="userService" >
  362.     <property name="userDao" ref="userDao"/>
  363. </bean>
  364. <bean id="userDao" />   ├── jdbc/<bean id="userService" >
  365.     <property name="userDao" ref="userDao"/>
  366. </bean>
  367. <bean id="userDao" /><bean id="userService" >
  368.     <property name="userDao" ref="userDao"/>
  369. </bean>
  370. <bean id="userDao" /><bean id="userService" >
  371.     <property name="userDao" ref="userDao"/>
  372. </bean>
  373. <bean id="userDao" /><bean id="userService" >
  374.     <property name="userDao" ref="userDao"/>
  375. </bean>
  376. <bean id="userDao" /><bean id="userService" >
  377.     <property name="userDao" ref="userDao"/>
  378. </bean>
  379. <bean id="userDao" /><bean id="userService" >
  380.     <property name="userDao" ref="userDao"/>
  381. </bean>
  382. <bean id="userDao" />   # JDBC模板│   │<bean id="userService" >
  383.     <property name="userDao" ref="userDao"/>
  384. </bean>
  385. <bean id="userDao" />   │   ├── JdbcTemplate.java<bean id="userService" >
  386.     <property name="userDao" ref="userDao"/>
  387. </bean>
  388. <bean id="userDao" /><bean id="userService" >
  389.     <property name="userDao" ref="userDao"/>
  390. </bean>
  391. <bean id="userDao" />   # JDBC模板类│   │<bean id="userService" >
  392.     <property name="userDao" ref="userDao"/>
  393. </bean>
  394. <bean id="userDao" />   │   └── RowMapper.java<bean id="userService" >
  395.     <property name="userDao" ref="userDao"/>
  396. </bean>
  397. <bean id="userDao" /><bean id="userService" >
  398.     <property name="userDao" ref="userDao"/>
  399. </bean>
  400. <bean id="userDao" /><bean id="userService" >
  401.     <property name="userDao" ref="userDao"/>
  402. </bean>
  403. <bean id="userDao" />  # 结果集映射│   │<bean id="userService" >
  404.     <property name="userDao" ref="userDao"/>
  405. </bean>
  406. <bean id="userDao" />   ││   │<bean id="userService" >
  407.     <property name="userDao" ref="userDao"/>
  408. </bean>
  409. <bean id="userDao" />   ├── web/<bean id="userService" >
  410.     <property name="userDao" ref="userDao"/>
  411. </bean>
  412. <bean id="userDao" /><bean id="userService" >
  413.     <property name="userDao" ref="userDao"/>
  414. </bean>
  415. <bean id="userDao" /><bean id="userService" >
  416.     <property name="userDao" ref="userDao"/>
  417. </bean>
  418. <bean id="userDao" /><bean id="userService" >
  419.     <property name="userDao" ref="userDao"/>
  420. </bean>
  421. <bean id="userDao" /><bean id="userService" >
  422.     <property name="userDao" ref="userDao"/>
  423. </bean>
  424. <bean id="userDao" /><bean id="userService" >
  425.     <property name="userDao" ref="userDao"/>
  426. </bean>
  427. <bean id="userDao" /><bean id="userService" >
  428.     <property name="userDao" ref="userDao"/>
  429. </bean>
  430. <bean id="userDao" /># Web MVC│   │<bean id="userService" >
  431.     <property name="userDao" ref="userDao"/>
  432. </bean>
  433. <bean id="userDao" />   │   ├── DispatcherServlet.java<bean id="userService" >
  434.     <property name="userDao" ref="userDao"/>
  435. </bean>
  436. <bean id="userDao" />  # 前端控制器│   │<bean id="userService" >
  437.     <property name="userDao" ref="userDao"/>
  438. </bean>
  439. <bean id="userDao" />   │   ├── HandlerMapping.java<bean id="userService" >
  440.     <property name="userDao" ref="userDao"/>
  441. </bean>
  442. <bean id="userDao" /><bean id="userService" >
  443.     <property name="userDao" ref="userDao"/>
  444. </bean>
  445. <bean id="userDao" /> # 处理器映射│   │<bean id="userService" >
  446.     <property name="userDao" ref="userDao"/>
  447. </bean>
  448. <bean id="userDao" />   │   ├── PathMatcher.java<bean id="userService" >
  449.     <property name="userDao" ref="userDao"/>
  450. </bean>
  451. <bean id="userDao" /><bean id="userService" >
  452.     <property name="userDao" ref="userDao"/>
  453. </bean>
  454. <bean id="userDao" /><bean id="userService" >
  455.     <property name="userDao" ref="userDao"/>
  456. </bean>
  457. <bean id="userDao" /># 路径匹配器│   │<bean id="userService" >
  458.     <property name="userDao" ref="userDao"/>
  459. </bean>
  460. <bean id="userDao" />   │   ├── ViewResult.java<bean id="userService" >
  461.     <property name="userDao" ref="userDao"/>
  462. </bean>
  463. <bean id="userDao" /><bean id="userService" >
  464.     <property name="userDao" ref="userDao"/>
  465. </bean>
  466. <bean id="userDao" /><bean id="userService" >
  467.     <property name="userDao" ref="userDao"/>
  468. </bean>
  469. <bean id="userDao" /> # 视图结果│   │<bean id="userService" >
  470.     <property name="userDao" ref="userDao"/>
  471. </bean>
  472. <bean id="userDao" />   │   ├── HttpRequestUtil.java<bean id="userService" >
  473.     <property name="userDao" ref="userDao"/>
  474. </bean>
  475. <bean id="userDao" /><bean id="userService" >
  476.     <property name="userDao" ref="userDao"/>
  477. </bean>
  478. <bean id="userDao" /># HTTP工具│   │<bean id="userService" >
  479.     <property name="userDao" ref="userDao"/>
  480. </bean>
  481. <bean id="userDao" />   │   └── JsonUtil.java<bean id="userService" >
  482.     <property name="userDao" ref="userDao"/>
  483. </bean>
  484. <bean id="userDao" /><bean id="userService" >
  485.     <property name="userDao" ref="userDao"/>
  486. </bean>
  487. <bean id="userDao" /><bean id="userService" >
  488.     <property name="userDao" ref="userDao"/>
  489. </bean>
  490. <bean id="userDao" />   # JSON工具│   │<bean id="userService" >
  491.     <property name="userDao" ref="userDao"/>
  492. </bean>
  493. <bean id="userDao" />   ││   │<bean id="userService" >
  494.     <property name="userDao" ref="userDao"/>
  495. </bean>
  496. <bean id="userDao" />   ├── exception/<bean id="userService" >
  497.     <property name="userDao" ref="userDao"/>
  498. </bean>
  499. <bean id="userDao" /><bean id="userService" >
  500.     <property name="userDao" ref="userDao"/>
  501. </bean>
  502. <bean id="userDao" /><bean id="userService" >
  503.     <property name="userDao" ref="userDao"/>
  504. </bean>
  505. <bean id="userDao" /><bean id="userService" >
  506.     <property name="userDao" ref="userDao"/>
  507. </bean>
  508. <bean id="userDao" /><bean id="userService" >
  509.     <property name="userDao" ref="userDao"/>
  510. </bean>
  511. <bean id="userDao" />  # 异常定义│   │<bean id="userService" >
  512.     <property name="userDao" ref="userDao"/>
  513. </bean>
  514. <bean id="userDao" />   │   ├── BeanCreationException.java│   │<bean id="userService" >
  515.     <property name="userDao" ref="userDao"/>
  516. </bean>
  517. <bean id="userDao" />   │   ├── BeanNotFoundException.java│   │<bean id="userService" >
  518.     <property name="userDao" ref="userDao"/>
  519. </bean>
  520. <bean id="userDao" />   │   └── CircularDependencyException.java│   │<bean id="userService" >
  521.     <property name="userDao" ref="userDao"/>
  522. </bean>
  523. <bean id="userDao" />   ││   │<bean id="userService" >
  524.     <property name="userDao" ref="userDao"/>
  525. </bean>
  526. <bean id="userDao" />   └── util/<bean id="userService" >
  527.     <property name="userDao" ref="userDao"/>
  528. </bean>
  529. <bean id="userDao" /><bean id="userService" >
  530.     <property name="userDao" ref="userDao"/>
  531. </bean>
  532. <bean id="userDao" /><bean id="userService" >
  533.     <property name="userDao" ref="userDao"/>
  534. </bean>
  535. <bean id="userDao" /><bean id="userService" >
  536.     <property name="userDao" ref="userDao"/>
  537. </bean>
  538. <bean id="userDao" /><bean id="userService" >
  539.     <property name="userDao" ref="userDao"/>
  540. </bean>
  541. <bean id="userDao" /><bean id="userService" >
  542.     <property name="userDao" ref="userDao"/>
  543. </bean>
  544. <bean id="userDao" />   # 工具类│   │<bean id="userService" >
  545.     <property name="userDao" ref="userDao"/>
  546. </bean>
  547. <bean id="userDao" /><bean id="userService" >
  548.     <property name="userDao" ref="userDao"/>
  549. </bean>
  550. <bean id="userDao" />   ├── ClassScanner.java<bean id="userService" >
  551.     <property name="userDao" ref="userDao"/>
  552. </bean>
  553. <bean id="userDao" /><bean id="userService" >
  554.     <property name="userDao" ref="userDao"/>
  555. </bean>
  556. <bean id="userDao" />   # 类扫描器│   │<bean id="userService" >
  557.     <property name="userDao" ref="userDao"/>
  558. </bean>
  559. <bean id="userDao" /><bean id="userService" >
  560.     <property name="userDao" ref="userDao"/>
  561. </bean>
  562. <bean id="userDao" />   └── StringUtils.java<bean id="userService" >
  563.     <property name="userDao" ref="userDao"/>
  564. </bean>
  565. <bean id="userDao" /><bean id="userService" >
  566.     <property name="userDao" ref="userDao"/>
  567. </bean>
  568. <bean id="userDao" /><bean id="userService" >
  569.     <property name="userDao" ref="userDao"/>
  570. </bean>
  571. <bean id="userDao" /># 字符串工具│   ││   └── test/<bean id="userService" >
  572.     <property name="userDao" ref="userDao"/>
  573. </bean>
  574. <bean id="userDao" /><bean id="userService" >
  575.     <property name="userDao" ref="userDao"/>
  576. </bean>
  577. <bean id="userDao" /><bean id="userService" >
  578.     <property name="userDao" ref="userDao"/>
  579. </bean>
  580. <bean id="userDao" /><bean id="userService" >
  581.     <property name="userDao" ref="userDao"/>
  582. </bean>
  583. <bean id="userDao" /><bean id="userService" >
  584.     <property name="userDao" ref="userDao"/>
  585. </bean>
  586. <bean id="userDao" /><bean id="userService" >
  587.     <property name="userDao" ref="userDao"/>
  588. </bean>
  589. <bean id="userDao" /><bean id="userService" >
  590.     <property name="userDao" ref="userDao"/>
  591. </bean>
  592. <bean id="userDao" /><bean id="userService" >
  593.     <property name="userDao" ref="userDao"/>
  594. </bean>
  595. <bean id="userDao" />   # 测试代码│<bean id="userService" >
  596.     <property name="userDao" ref="userDao"/>
  597. </bean>
  598. <bean id="userDao" />   ├── java/│<bean id="userService" >
  599.     <property name="userDao" ref="userDao"/>
  600. </bean>
  601. <bean id="userDao" />   │   ├── IoCTest.java<bean id="userService" >
  602.     <property name="userDao" ref="userDao"/>
  603. </bean>
  604. <bean id="userDao" /><bean id="userService" >
  605.     <property name="userDao" ref="userDao"/>
  606. </bean>
  607. <bean id="userDao" /><bean id="userService" >
  608.     <property name="userDao" ref="userDao"/>
  609. </bean>
  610. <bean id="userDao" /><bean id="userService" >
  611.     <property name="userDao" ref="userDao"/>
  612. </bean>
  613. <bean id="userDao" /><bean id="userService" >
  614.     <property name="userDao" ref="userDao"/>
  615. </bean>
  616. <bean id="userDao" /># IoC容器测试│<bean id="userService" >
  617.     <property name="userDao" ref="userDao"/>
  618. </bean>
  619. <bean id="userDao" />   │   ├── AopTest.java<bean id="userService" >
  620.     <property name="userDao" ref="userDao"/>
  621. </bean>
  622. <bean id="userDao" /><bean id="userService" >
  623.     <property name="userDao" ref="userDao"/>
  624. </bean>
  625. <bean id="userDao" /><bean id="userService" >
  626.     <property name="userDao" ref="userDao"/>
  627. </bean>
  628. <bean id="userDao" /><bean id="userService" >
  629.     <property name="userDao" ref="userDao"/>
  630. </bean>
  631. <bean id="userDao" /><bean id="userService" >
  632.     <property name="userDao" ref="userDao"/>
  633. </bean>
  634. <bean id="userDao" /># AOP测试│<bean id="userService" >
  635.     <property name="userDao" ref="userDao"/>
  636. </bean>
  637. <bean id="userDao" />   │   ├── MvcTest.java<bean id="userService" >
  638.     <property name="userDao" ref="userDao"/>
  639. </bean>
  640. <bean id="userDao" /><bean id="userService" >
  641.     <property name="userDao" ref="userDao"/>
  642. </bean>
  643. <bean id="userDao" /><bean id="userService" >
  644.     <property name="userDao" ref="userDao"/>
  645. </bean>
  646. <bean id="userDao" /><bean id="userService" >
  647.     <property name="userDao" ref="userDao"/>
  648. </bean>
  649. <bean id="userDao" /><bean id="userService" >
  650.     <property name="userDao" ref="userDao"/>
  651. </bean>
  652. <bean id="userDao" /># Web MVC测试│<bean id="userService" >
  653.     <property name="userDao" ref="userDao"/>
  654. </bean>
  655. <bean id="userDao" />   │   └── JdbcTest.java<bean id="userService" >
  656.     <property name="userDao" ref="userDao"/>
  657. </bean>
  658. <bean id="userDao" /><bean id="userService" >
  659.     <property name="userDao" ref="userDao"/>
  660. </bean>
  661. <bean id="userDao" /><bean id="userService" >
  662.     <property name="userDao" ref="userDao"/>
  663. </bean>
  664. <bean id="userDao" /><bean id="userService" >
  665.     <property name="userDao" ref="userDao"/>
  666. </bean>
  667. <bean id="userDao" />   # JDBC测试│<bean id="userService" >
  668.     <property name="userDao" ref="userDao"/>
  669. </bean>
  670. <bean id="userDao" />   └── resources/│<bean id="userService" >
  671.     <property name="userDao" ref="userDao"/>
  672. </bean>
  673. <bean id="userDao" /><bean id="userService" >
  674.     <property name="userDao" ref="userDao"/>
  675. </bean>
  676. <bean id="userDao" />   └── test-data.sql│└── examples/<bean id="userService" >
  677.     <property name="userDao" ref="userDao"/>
  678. </bean>
  679. <bean id="userDao" /><bean id="userService" >
  680.     <property name="userDao" ref="userDao"/>
  681. </bean>
  682. <bean id="userDao" /><bean id="userService" >
  683.     <property name="userDao" ref="userDao"/>
  684. </bean>
  685. <bean id="userDao" /><bean id="userService" >
  686.     <property name="userDao" ref="userDao"/>
  687. </bean>
  688. <bean id="userDao" /><bean id="userService" >
  689.     <property name="userDao" ref="userDao"/>
  690. </bean>
  691. <bean id="userDao" /><bean id="userService" >
  692.     <property name="userDao" ref="userDao"/>
  693. </bean>
  694. <bean id="userDao" /><bean id="userService" >
  695.     <property name="userDao" ref="userDao"/>
  696. </bean>
  697. <bean id="userDao" /><bean id="userService" >
  698.     <property name="userDao" ref="userDao"/>
  699. </bean>
  700. <bean id="userDao" /><bean id="userService" >
  701.     <property name="userDao" ref="userDao"/>
  702. </bean>
  703. <bean id="userDao" /># 示例项目<bean id="userService" >
  704.     <property name="userDao" ref="userDao"/>
  705. </bean>
  706. <bean id="userDao" />├── user-demo/<bean id="userService" >
  707.     <property name="userDao" ref="userDao"/>
  708. </bean>
  709. <bean id="userDao" /><bean id="userService" >
  710.     <property name="userDao" ref="userDao"/>
  711. </bean>
  712. <bean id="userDao" /><bean id="userService" >
  713.     <property name="userDao" ref="userDao"/>
  714. </bean>
  715. <bean id="userDao" /><bean id="userService" >
  716.     <property name="userDao" ref="userDao"/>
  717. </bean>
  718. <bean id="userDao" /><bean id="userService" >
  719.     <property name="userDao" ref="userDao"/>
  720. </bean>
  721. <bean id="userDao" /><bean id="userService" >
  722.     <property name="userDao" ref="userDao"/>
  723. </bean>
  724. <bean id="userDao" /><bean id="userService" >
  725.     <property name="userDao" ref="userDao"/>
  726. </bean>
  727. <bean id="userDao" />   # 用户管理示例<bean id="userService" >
  728.     <property name="userDao" ref="userDao"/>
  729. </bean>
  730. <bean id="userDao" />│   ├── src/<bean id="userService" >
  731.     <property name="userDao" ref="userDao"/>
  732. </bean>
  733. <bean id="userDao" />│   │   └── main/java/com/github/microwind/userdemo/<bean id="userService" >
  734.     <property name="userDao" ref="userDao"/>
  735. </bean>
  736. <bean id="userDao" />│   │<bean id="userService" >
  737.     <property name="userDao" ref="userDao"/>
  738. </bean>
  739. <bean id="userDao" />   ├── UserDemoApplication.java<bean id="userService" >
  740.     <property name="userDao" ref="userDao"/>
  741. </bean>
  742. <bean id="userDao" /># 启动类<bean id="userService" >
  743.     <property name="userDao" ref="userDao"/>
  744. </bean>
  745. <bean id="userDao" />│   │<bean id="userService" >
  746.     <property name="userDao" ref="userDao"/>
  747. </bean>
  748. <bean id="userDao" />   ├── config/<bean id="userService" >
  749.     <property name="userDao" ref="userDao"/>
  750. </bean>
  751. <bean id="userDao" /><bean id="userService" >
  752.     <property name="userDao" ref="userDao"/>
  753. </bean>
  754. <bean id="userDao" /><bean id="userService" >
  755.     <property name="userDao" ref="userDao"/>
  756. </bean>
  757. <bean id="userDao" /><bean id="userService" >
  758.     <property name="userDao" ref="userDao"/>
  759. </bean>
  760. <bean id="userDao" /><bean id="userService" >
  761.     <property name="userDao" ref="userDao"/>
  762. </bean>
  763. <bean id="userDao" /> # 配置层<bean id="userService" >
  764.     <property name="userDao" ref="userDao"/>
  765. </bean>
  766. <bean id="userDao" />│   │<bean id="userService" >
  767.     <property name="userDao" ref="userDao"/>
  768. </bean>
  769. <bean id="userDao" />   │   └── DataSourceConfig.java   # 数据源配置<bean id="userService" >
  770.     <property name="userDao" ref="userDao"/>
  771. </bean>
  772. <bean id="userDao" />│   │<bean id="userService" >
  773.     <property name="userDao" ref="userDao"/>
  774. </bean>
  775. <bean id="userDao" />   ├── controller/<bean id="userService" >
  776.     <property name="userDao" ref="userDao"/>
  777. </bean>
  778. <bean id="userDao" /><bean id="userService" >
  779.     <property name="userDao" ref="userDao"/>
  780. </bean>
  781. <bean id="userDao" /><bean id="userService" >
  782.     <property name="userDao" ref="userDao"/>
  783. </bean>
  784. <bean id="userDao" /><bean id="userService" >
  785.     <property name="userDao" ref="userDao"/>
  786. </bean>
  787. <bean id="userDao" /> # 控制器层<bean id="userService" >
  788.     <property name="userDao" ref="userDao"/>
  789. </bean>
  790. <bean id="userDao" />│   │<bean id="userService" >
  791.     <property name="userDao" ref="userDao"/>
  792. </bean>
  793. <bean id="userDao" />   │   ├── UserController.java<bean id="userService" >
  794.     <property name="userDao" ref="userDao"/>
  795. </bean>
  796. <bean id="userDao" /> # 用户CRUD接口<bean id="userService" >
  797.     <property name="userDao" ref="userDao"/>
  798. </bean>
  799. <bean id="userDao" />│   │<bean id="userService" >
  800.     <property name="userDao" ref="userDao"/>
  801. </bean>
  802. <bean id="userDao" />   │   ├── StudentController.java  # 学生管理<bean id="userService" >
  803.     <property name="userDao" ref="userDao"/>
  804. </bean>
  805. <bean id="userDao" />│   │<bean id="userService" >
  806.     <property name="userDao" ref="userDao"/>
  807. </bean>
  808. <bean id="userDao" />   │   └── ClassController.java<bean id="userService" >
  809.     <property name="userDao" ref="userDao"/>
  810. </bean>
  811. <bean id="userDao" /># 班级管理<bean id="userService" >
  812.     <property name="userDao" ref="userDao"/>
  813. </bean>
  814. <bean id="userDao" />│   │<bean id="userService" >
  815.     <property name="userDao" ref="userDao"/>
  816. </bean>
  817. <bean id="userDao" />   ├── service/<bean id="userService" >
  818.     <property name="userDao" ref="userDao"/>
  819. </bean>
  820. <bean id="userDao" /><bean id="userService" >
  821.     <property name="userDao" ref="userDao"/>
  822. </bean>
  823. <bean id="userDao" /><bean id="userService" >
  824.     <property name="userDao" ref="userDao"/>
  825. </bean>
  826. <bean id="userDao" /><bean id="userService" >
  827.     <property name="userDao" ref="userDao"/>
  828. </bean>
  829. <bean id="userDao" /><bean id="userService" >
  830.     <property name="userDao" ref="userDao"/>
  831. </bean>
  832. <bean id="userDao" /># 服务层<bean id="userService" >
  833.     <property name="userDao" ref="userDao"/>
  834. </bean>
  835. <bean id="userDao" />│   │<bean id="userService" >
  836.     <property name="userDao" ref="userDao"/>
  837. </bean>
  838. <bean id="userDao" />   │   ├── UserService.java<bean id="userService" >
  839.     <property name="userDao" ref="userDao"/>
  840. </bean>
  841. <bean id="userDao" />│   │<bean id="userService" >
  842.     <property name="userDao" ref="userDao"/>
  843. </bean>
  844. <bean id="userDao" />   │   ├── StudentService.java<bean id="userService" >
  845.     <property name="userDao" ref="userDao"/>
  846. </bean>
  847. <bean id="userDao" />│   │<bean id="userService" >
  848.     <property name="userDao" ref="userDao"/>
  849. </bean>
  850. <bean id="userDao" />   │   └── ClassService.java<bean id="userService" >
  851.     <property name="userDao" ref="userDao"/>
  852. </bean>
  853. <bean id="userDao" />│   │<bean id="userService" >
  854.     <property name="userDao" ref="userDao"/>
  855. </bean>
  856. <bean id="userDao" />   ├── dao/<bean id="userService" >
  857.     <property name="userDao" ref="userDao"/>
  858. </bean>
  859. <bean id="userDao" /><bean id="userService" >
  860.     <property name="userDao" ref="userDao"/>
  861. </bean>
  862. <bean id="userDao" /><bean id="userService" >
  863.     <property name="userDao" ref="userDao"/>
  864. </bean>
  865. <bean id="userDao" /><bean id="userService" >
  866.     <property name="userDao" ref="userDao"/>
  867. </bean>
  868. <bean id="userDao" /><bean id="userService" >
  869.     <property name="userDao" ref="userDao"/>
  870. </bean>
  871. <bean id="userDao" /><bean id="userService" >
  872.     <property name="userDao" ref="userDao"/>
  873. </bean>
  874. <bean id="userDao" /># 数据访问层<bean id="userService" >
  875.     <property name="userDao" ref="userDao"/>
  876. </bean>
  877. <bean id="userDao" />│   │<bean id="userService" >
  878.     <property name="userDao" ref="userDao"/>
  879. </bean>
  880. <bean id="userDao" />   │   ├── UserDao.java<bean id="userService" >
  881.     <property name="userDao" ref="userDao"/>
  882. </bean>
  883. <bean id="userDao" /><bean id="userService" >
  884.     <property name="userDao" ref="userDao"/>
  885. </bean>
  886. <bean id="userDao" />   # JdbcTemplate CRUD<bean id="userService" >
  887.     <property name="userDao" ref="userDao"/>
  888. </bean>
  889. <bean id="userDao" />│   │<bean id="userService" >
  890.     <property name="userDao" ref="userDao"/>
  891. </bean>
  892. <bean id="userDao" />   │   ├── StudentDao.java<bean id="userService" >
  893.     <property name="userDao" ref="userDao"/>
  894. </bean>
  895. <bean id="userDao" />│   │<bean id="userService" >
  896.     <property name="userDao" ref="userDao"/>
  897. </bean>
  898. <bean id="userDao" />   │   └── ClassDao.java<bean id="userService" >
  899.     <property name="userDao" ref="userDao"/>
  900. </bean>
  901. <bean id="userDao" />│   │<bean id="userService" >
  902.     <property name="userDao" ref="userDao"/>
  903. </bean>
  904. <bean id="userDao" />   ├── model/<bean id="userService" >
  905.     <property name="userDao" ref="userDao"/>
  906. </bean>
  907. <bean id="userDao" /><bean id="userService" >
  908.     <property name="userDao" ref="userDao"/>
  909. </bean>
  910. <bean id="userDao" /><bean id="userService" >
  911.     <property name="userDao" ref="userDao"/>
  912. </bean>
  913. <bean id="userDao" /><bean id="userService" >
  914.     <property name="userDao" ref="userDao"/>
  915. </bean>
  916. <bean id="userDao" /><bean id="userService" >
  917.     <property name="userDao" ref="userDao"/>
  918. </bean>
  919. <bean id="userDao" />  # 数据模型<bean id="userService" >
  920.     <property name="userDao" ref="userDao"/>
  921. </bean>
  922. <bean id="userDao" />│   │<bean id="userService" >
  923.     <property name="userDao" ref="userDao"/>
  924. </bean>
  925. <bean id="userDao" />   │   ├── User.java<bean id="userService" >
  926.     <property name="userDao" ref="userDao"/>
  927. </bean>
  928. <bean id="userDao" />│   │<bean id="userService" >
  929.     <property name="userDao" ref="userDao"/>
  930. </bean>
  931. <bean id="userDao" />   │   ├── Student.java<bean id="userService" >
  932.     <property name="userDao" ref="userDao"/>
  933. </bean>
  934. <bean id="userDao" />│   │<bean id="userService" >
  935.     <property name="userDao" ref="userDao"/>
  936. </bean>
  937. <bean id="userDao" />   │   └── ClassInfo.java<bean id="userService" >
  938.     <property name="userDao" ref="userDao"/>
  939. </bean>
  940. <bean id="userDao" />│   │<bean id="userService" >
  941.     <property name="userDao" ref="userDao"/>
  942. </bean>
  943. <bean id="userDao" />   └── utils/<bean id="userService" >
  944.     <property name="userDao" ref="userDao"/>
  945. </bean>
  946. <bean id="userDao" /><bean id="userService" >
  947.     <property name="userDao" ref="userDao"/>
  948. </bean>
  949. <bean id="userDao" /><bean id="userService" >
  950.     <property name="userDao" ref="userDao"/>
  951. </bean>
  952. <bean id="userDao" /><bean id="userService" >
  953.     <property name="userDao" ref="userDao"/>
  954. </bean>
  955. <bean id="userDao" /><bean id="userService" >
  956.     <property name="userDao" ref="userDao"/>
  957. </bean>
  958. <bean id="userDao" />  # 工具类<bean id="userService" >
  959.     <property name="userDao" ref="userDao"/>
  960. </bean>
  961. <bean id="userDao" />│   │<bean id="userService" >
  962.     <property name="userDao" ref="userDao"/>
  963. </bean>
  964. <bean id="userDao" /><bean id="userService" >
  965.     <property name="userDao" ref="userDao"/>
  966. </bean>
  967. <bean id="userDao" />   ├── ApiResponse.java<bean id="userService" >
  968.     <property name="userDao" ref="userDao"/>
  969. </bean>
  970. <bean id="userDao" /><bean id="userService" >
  971.     <property name="userDao" ref="userDao"/>
  972. </bean>
  973. <bean id="userDao" /># API响应封装<bean id="userService" >
  974.     <property name="userDao" ref="userDao"/>
  975. </bean>
  976. <bean id="userDao" />│   │<bean id="userService" >
  977.     <property name="userDao" ref="userDao"/>
  978. </bean>
  979. <bean id="userDao" /><bean id="userService" >
  980.     <property name="userDao" ref="userDao"/>
  981. </bean>
  982. <bean id="userDao" />   ├── PageResult.java<bean id="userService" >
  983.     <property name="userDao" ref="userDao"/>
  984. </bean>
  985. <bean id="userDao" /><bean id="userService" >
  986.     <property name="userDao" ref="userDao"/>
  987. </bean>
  988. <bean id="userDao" /> # 分页结果<bean id="userService" >
  989.     <property name="userDao" ref="userDao"/>
  990. </bean>
  991. <bean id="userDao" />│   │<bean id="userService" >
  992.     <property name="userDao" ref="userDao"/>
  993. </bean>
  994. <bean id="userDao" /><bean id="userService" >
  995.     <property name="userDao" ref="userDao"/>
  996. </bean>
  997. <bean id="userDao" />   └── JsonUtil.java<bean id="userService" >
  998.     <property name="userDao" ref="userDao"/>
  999. </bean>
  1000. <bean id="userDao" />│   ├── init-db.sql<bean id="userService" >
  1001.     <property name="userDao" ref="userDao"/>
  1002. </bean>
  1003. <bean id="userDao" /><bean id="userService" >
  1004.     <property name="userDao" ref="userDao"/>
  1005. </bean>
  1006. <bean id="userDao" /><bean id="userService" >
  1007.     <property name="userDao" ref="userDao"/>
  1008. </bean>
  1009. <bean id="userDao" /><bean id="userService" >
  1010.     <property name="userDao" ref="userDao"/>
  1011. </bean>
  1012. <bean id="userDao" /><bean id="userService" >
  1013.     <property name="userDao" ref="userDao"/>
  1014. </bean>
  1015. <bean id="userDao" /><bean id="userService" >
  1016.     <property name="userDao" ref="userDao"/>
  1017. </bean>
  1018. <bean id="userDao" /> # 数据库初始化脚本<bean id="userService" >
  1019.     <property name="userDao" ref="userDao"/>
  1020. </bean>
  1021. <bean id="userDao" />│   └── test-user-api.sh<bean id="userService" >
  1022.     <property name="userDao" ref="userDao"/>
  1023. </bean>
  1024. <bean id="userDao" /><bean id="userService" >
  1025.     <property name="userDao" ref="userDao"/>
  1026. </bean>
  1027. <bean id="userDao" /><bean id="userService" >
  1028.     <property name="userDao" ref="userDao"/>
  1029. </bean>
  1030. <bean id="userDao" /><bean id="userService" >
  1031.     <property name="userDao" ref="userDao"/>
  1032. </bean>
  1033. <bean id="userDao" /><bean id="userService" >
  1034.     <property name="userDao" ref="userDao"/>
  1035. </bean>
  1036. <bean id="userDao" /># API测试脚本<bean id="userService" >
  1037.     <property name="userDao" ref="userDao"/>
  1038. </bean>
  1039. <bean id="userDao" />│<bean id="userService" >
  1040.     <property name="userDao" ref="userDao"/>
  1041. </bean>
  1042. <bean id="userDao" />└── web-demo/<bean id="userService" >
  1043.     <property name="userDao" ref="userDao"/>
  1044. </bean>
  1045. <bean id="userDao" /><bean id="userService" >
  1046.     <property name="userDao" ref="userDao"/>
  1047. </bean>
  1048. <bean id="userDao" /><bean id="userService" >
  1049.     <property name="userDao" ref="userDao"/>
  1050. </bean>
  1051. <bean id="userDao" /><bean id="userService" >
  1052.     <property name="userDao" ref="userDao"/>
  1053. </bean>
  1054. <bean id="userDao" /><bean id="userService" >
  1055.     <property name="userDao" ref="userDao"/>
  1056. </bean>
  1057. <bean id="userDao" /><bean id="userService" >
  1058.     <property name="userDao" ref="userDao"/>
  1059. </bean>
  1060. <bean id="userDao" /><bean id="userService" >
  1061.     <property name="userDao" ref="userDao"/>
  1062. </bean>
  1063. <bean id="userDao" /><bean id="userService" >
  1064.     <property name="userDao" ref="userDao"/>
  1065. </bean>
  1066. <bean id="userDao" /># Web应用示例<bean id="userService" >
  1067.     <property name="userDao" ref="userDao"/>
  1068. </bean>
  1069. <bean id="userDao" /><bean id="userService" >
  1070.     <property name="userDao" ref="userDao"/>
  1071. </bean>
  1072. <bean id="userDao" />├── src/<bean id="userService" >
  1073.     <property name="userDao" ref="userDao"/>
  1074. </bean>
  1075. <bean id="userDao" /><bean id="userService" >
  1076.     <property name="userDao" ref="userDao"/>
  1077. </bean>
  1078. <bean id="userDao" />│   └── main/java/com/github/microwind/webdemo/<bean id="userService" >
  1079.     <property name="userDao" ref="userDao"/>
  1080. </bean>
  1081. <bean id="userDao" /><bean id="userService" >
  1082.     <property name="userDao" ref="userDao"/>
  1083. </bean>
  1084. <bean id="userDao" />│<bean id="userService" >
  1085.     <property name="userDao" ref="userDao"/>
  1086. </bean>
  1087. <bean id="userDao" />   ├── WebDemoApplication.java<bean id="userService" >
  1088.     <property name="userDao" ref="userDao"/>
  1089. </bean>
  1090. <bean id="userDao" /> # 启动类<bean id="userService" >
  1091.     <property name="userDao" ref="userDao"/>
  1092. </bean>
  1093. <bean id="userDao" /><bean id="userService" >
  1094.     <property name="userDao" ref="userDao"/>
  1095. </bean>
  1096. <bean id="userDao" />│<bean id="userService" >
  1097.     <property name="userDao" ref="userDao"/>
  1098. </bean>
  1099. <bean id="userDao" />   ├── controller/<bean id="userService" >
  1100.     <property name="userDao" ref="userDao"/>
  1101. </bean>
  1102. <bean id="userDao" /><bean id="userService" >
  1103.     <property name="userDao" ref="userDao"/>
  1104. </bean>
  1105. <bean id="userDao" /><bean id="userService" >
  1106.     <property name="userDao" ref="userDao"/>
  1107. </bean>
  1108. <bean id="userDao" /><bean id="userService" >
  1109.     <property name="userDao" ref="userDao"/>
  1110. </bean>
  1111. <bean id="userDao" /> # 控制器层<bean id="userService" >
  1112.     <property name="userDao" ref="userDao"/>
  1113. </bean>
  1114. <bean id="userDao" /><bean id="userService" >
  1115.     <property name="userDao" ref="userDao"/>
  1116. </bean>
  1117. <bean id="userDao" />│<bean id="userService" >
  1118.     <property name="userDao" ref="userDao"/>
  1119. </bean>
  1120. <bean id="userDao" />   │   ├── HomeController.java<bean id="userService" >
  1121.     <property name="userDao" ref="userDao"/>
  1122. </bean>
  1123. <bean id="userDao" /> # 首页<bean id="userService" >
  1124.     <property name="userDao" ref="userDao"/>
  1125. </bean>
  1126. <bean id="userDao" /><bean id="userService" >
  1127.     <property name="userDao" ref="userDao"/>
  1128. </bean>
  1129. <bean id="userDao" />│<bean id="userService" >
  1130.     <property name="userDao" ref="userDao"/>
  1131. </bean>
  1132. <bean id="userDao" />   │   ├── ProductController.java  # 产品中心<bean id="userService" >
  1133.     <property name="userDao" ref="userDao"/>
  1134. </bean>
  1135. <bean id="userDao" /><bean id="userService" >
  1136.     <property name="userDao" ref="userDao"/>
  1137. </bean>
  1138. <bean id="userDao" />│<bean id="userService" >
  1139.     <property name="userDao" ref="userDao"/>
  1140. </bean>
  1141. <bean id="userDao" />   │   ├── NewsController.java<bean id="userService" >
  1142.     <property name="userDao" ref="userDao"/>
  1143. </bean>
  1144. <bean id="userDao" /> # 新闻资讯<bean id="userService" >
  1145.     <property name="userDao" ref="userDao"/>
  1146. </bean>
  1147. <bean id="userDao" /><bean id="userService" >
  1148.     <property name="userDao" ref="userDao"/>
  1149. </bean>
  1150. <bean id="userDao" />│<bean id="userService" >
  1151.     <property name="userDao" ref="userDao"/>
  1152. </bean>
  1153. <bean id="userDao" />   │   ├── AdminController.java<bean id="userService" >
  1154.     <property name="userDao" ref="userDao"/>
  1155. </bean>
  1156. <bean id="userDao" /># 后台管理<bean id="userService" >
  1157.     <property name="userDao" ref="userDao"/>
  1158. </bean>
  1159. <bean id="userDao" /><bean id="userService" >
  1160.     <property name="userDao" ref="userDao"/>
  1161. </bean>
  1162. <bean id="userDao" />│<bean id="userService" >
  1163.     <property name="userDao" ref="userDao"/>
  1164. </bean>
  1165. <bean id="userDao" />   │   └── ArticleController.java  # 文章CRUD<bean id="userService" >
  1166.     <property name="userDao" ref="userDao"/>
  1167. </bean>
  1168. <bean id="userDao" /><bean id="userService" >
  1169.     <property name="userDao" ref="userDao"/>
  1170. </bean>
  1171. <bean id="userDao" />│<bean id="userService" >
  1172.     <property name="userDao" ref="userDao"/>
  1173. </bean>
  1174. <bean id="userDao" />   ├── service/<bean id="userService" >
  1175.     <property name="userDao" ref="userDao"/>
  1176. </bean>
  1177. <bean id="userDao" /><bean id="userService" >
  1178.     <property name="userDao" ref="userDao"/>
  1179. </bean>
  1180. <bean id="userDao" /><bean id="userService" >
  1181.     <property name="userDao" ref="userDao"/>
  1182. </bean>
  1183. <bean id="userDao" /><bean id="userService" >
  1184.     <property name="userDao" ref="userDao"/>
  1185. </bean>
  1186. <bean id="userDao" /><bean id="userService" >
  1187.     <property name="userDao" ref="userDao"/>
  1188. </bean>
  1189. <bean id="userDao" /># 服务层<bean id="userService" >
  1190.     <property name="userDao" ref="userDao"/>
  1191. </bean>
  1192. <bean id="userDao" /><bean id="userService" >
  1193.     <property name="userDao" ref="userDao"/>
  1194. </bean>
  1195. <bean id="userDao" />│<bean id="userService" >
  1196.     <property name="userDao" ref="userDao"/>
  1197. </bean>
  1198. <bean id="userDao" />   │   ├── ColumnService.java<bean id="userService" >
  1199.     <property name="userDao" ref="userDao"/>
  1200. </bean>
  1201. <bean id="userDao" /><bean id="userService" >
  1202.     <property name="userDao" ref="userDao"/>
  1203. </bean>
  1204. <bean id="userDao" />│<bean id="userService" >
  1205.     <property name="userDao" ref="userDao"/>
  1206. </bean>
  1207. <bean id="userDao" />   │   └── ArticleService.java<bean id="userService" >
  1208.     <property name="userDao" ref="userDao"/>
  1209. </bean>
  1210. <bean id="userDao" /><bean id="userService" >
  1211.     <property name="userDao" ref="userDao"/>
  1212. </bean>
  1213. <bean id="userDao" />│<bean id="userService" >
  1214.     <property name="userDao" ref="userDao"/>
  1215. </bean>
  1216. <bean id="userDao" />   ├── dao/<bean id="userService" >
  1217.     <property name="userDao" ref="userDao"/>
  1218. </bean>
  1219. <bean id="userDao" /><bean id="userService" >
  1220.     <property name="userDao" ref="userDao"/>
  1221. </bean>
  1222. <bean id="userDao" /><bean id="userService" >
  1223.     <property name="userDao" ref="userDao"/>
  1224. </bean>
  1225. <bean id="userDao" /><bean id="userService" >
  1226.     <property name="userDao" ref="userDao"/>
  1227. </bean>
  1228. <bean id="userDao" /><bean id="userService" >
  1229.     <property name="userDao" ref="userDao"/>
  1230. </bean>
  1231. <bean id="userDao" /><bean id="userService" >
  1232.     <property name="userDao" ref="userDao"/>
  1233. </bean>
  1234. <bean id="userDao" /># 数据访问层<bean id="userService" >
  1235.     <property name="userDao" ref="userDao"/>
  1236. </bean>
  1237. <bean id="userDao" /><bean id="userService" >
  1238.     <property name="userDao" ref="userDao"/>
  1239. </bean>
  1240. <bean id="userDao" />│<bean id="userService" >
  1241.     <property name="userDao" ref="userDao"/>
  1242. </bean>
  1243. <bean id="userDao" />   │   ├── ColumnDao.java<bean id="userService" >
  1244.     <property name="userDao" ref="userDao"/>
  1245. </bean>
  1246. <bean id="userDao" /><bean id="userService" >
  1247.     <property name="userDao" ref="userDao"/>
  1248. </bean>
  1249. <bean id="userDao" />│<bean id="userService" >
  1250.     <property name="userDao" ref="userDao"/>
  1251. </bean>
  1252. <bean id="userDao" />   │   └── ArticleDao.java<bean id="userService" >
  1253.     <property name="userDao" ref="userDao"/>
  1254. </bean>
  1255. <bean id="userDao" /><bean id="userService" >
  1256.     <property name="userDao" ref="userDao"/>
  1257. </bean>
  1258. <bean id="userDao" />│<bean id="userService" >
  1259.     <property name="userDao" ref="userDao"/>
  1260. </bean>
  1261. <bean id="userDao" />   ├── model/<bean id="userService" >
  1262.     <property name="userDao" ref="userDao"/>
  1263. </bean>
  1264. <bean id="userDao" /><bean id="userService" >
  1265.     <property name="userDao" ref="userDao"/>
  1266. </bean>
  1267. <bean id="userDao" /><bean id="userService" >
  1268.     <property name="userDao" ref="userDao"/>
  1269. </bean>
  1270. <bean id="userDao" /><bean id="userService" >
  1271.     <property name="userDao" ref="userDao"/>
  1272. </bean>
  1273. <bean id="userDao" /><bean id="userService" >
  1274.     <property name="userDao" ref="userDao"/>
  1275. </bean>
  1276. <bean id="userDao" />  # 数据模型<bean id="userService" >
  1277.     <property name="userDao" ref="userDao"/>
  1278. </bean>
  1279. <bean id="userDao" /><bean id="userService" >
  1280.     <property name="userDao" ref="userDao"/>
  1281. </bean>
  1282. <bean id="userDao" />│<bean id="userService" >
  1283.     <property name="userDao" ref="userDao"/>
  1284. </bean>
  1285. <bean id="userDao" />   │   ├── Column.java<bean id="userService" >
  1286.     <property name="userDao" ref="userDao"/>
  1287. </bean>
  1288. <bean id="userDao" /><bean id="userService" >
  1289.     <property name="userDao" ref="userDao"/>
  1290. </bean>
  1291. <bean id="userDao" /><bean id="userService" >
  1292.     <property name="userDao" ref="userDao"/>
  1293. </bean>
  1294. <bean id="userDao" /> # 栏目<bean id="userService" >
  1295.     <property name="userDao" ref="userDao"/>
  1296. </bean>
  1297. <bean id="userDao" /><bean id="userService" >
  1298.     <property name="userDao" ref="userDao"/>
  1299. </bean>
  1300. <bean id="userDao" />│<bean id="userService" >
  1301.     <property name="userDao" ref="userDao"/>
  1302. </bean>
  1303. <bean id="userDao" />   │   └── Article.java<bean id="userService" >
  1304.     <property name="userDao" ref="userDao"/>
  1305. </bean>
  1306. <bean id="userDao" /><bean id="userService" >
  1307.     <property name="userDao" ref="userDao"/>
  1308. </bean>
  1309. <bean id="userDao" /><bean id="userService" >
  1310.     <property name="userDao" ref="userDao"/>
  1311. </bean>
  1312. <bean id="userDao" /># 文章<bean id="userService" >
  1313.     <property name="userDao" ref="userDao"/>
  1314. </bean>
  1315. <bean id="userDao" /><bean id="userService" >
  1316.     <property name="userDao" ref="userDao"/>
  1317. </bean>
  1318. <bean id="userDao" />│<bean id="userService" >
  1319.     <property name="userDao" ref="userDao"/>
  1320. </bean>
  1321. <bean id="userDao" />   └── utils/<bean id="userService" >
  1322.     <property name="userDao" ref="userDao"/>
  1323. </bean>
  1324. <bean id="userDao" /><bean id="userService" >
  1325.     <property name="userDao" ref="userDao"/>
  1326. </bean>
  1327. <bean id="userDao" /><bean id="userService" >
  1328.     <property name="userDao" ref="userDao"/>
  1329. </bean>
  1330. <bean id="userDao" /><bean id="userService" >
  1331.     <property name="userDao" ref="userDao"/>
  1332. </bean>
  1333. <bean id="userDao" /><bean id="userService" >
  1334.     <property name="userDao" ref="userDao"/>
  1335. </bean>
  1336. <bean id="userDao" />  # 工具类<bean id="userService" >
  1337.     <property name="userDao" ref="userDao"/>
  1338. </bean>
  1339. <bean id="userDao" /><bean id="userService" >
  1340.     <property name="userDao" ref="userDao"/>
  1341. </bean>
  1342. <bean id="userDao" />│<bean id="userService" >
  1343.     <property name="userDao" ref="userDao"/>
  1344. </bean>
  1345. <bean id="userDao" /><bean id="userService" >
  1346.     <property name="userDao" ref="userDao"/>
  1347. </bean>
  1348. <bean id="userDao" />   ├── ResponseUtils.java<bean id="userService" >
  1349.     <property name="userDao" ref="userDao"/>
  1350. </bean>
  1351. <bean id="userDao" /><bean id="userService" >
  1352.     <property name="userDao" ref="userDao"/>
  1353. </bean>
  1354. <bean id="userDao" />│<bean id="userService" >
  1355.     <property name="userDao" ref="userDao"/>
  1356. </bean>
  1357. <bean id="userDao" /><bean id="userService" >
  1358.     <property name="userDao" ref="userDao"/>
  1359. </bean>
  1360. <bean id="userDao" />   ├── RequestUtils.java<bean id="userService" >
  1361.     <property name="userDao" ref="userDao"/>
  1362. </bean>
  1363. <bean id="userDao" /><bean id="userService" >
  1364.     <property name="userDao" ref="userDao"/>
  1365. </bean>
  1366. <bean id="userDao" />│<bean id="userService" >
  1367.     <property name="userDao" ref="userDao"/>
  1368. </bean>
  1369. <bean id="userDao" /><bean id="userService" >
  1370.     <property name="userDao" ref="userDao"/>
  1371. </bean>
  1372. <bean id="userDao" />   └── ResponseBody.java<bean id="userService" >
  1373.     <property name="userDao" ref="userDao"/>
  1374. </bean>
  1375. <bean id="userDao" /><bean id="userService" >
  1376.     <property name="userDao" ref="userDao"/>
  1377. </bean>
  1378. <bean id="userDao" />└── README.md
复制代码
核心模块说明:
模块包名核心类行数说明注解annotation20个注解类~350定义框架的注解体系IoC容器coreSpringWindApplicationContext~730容器核心,Bean管理,三级缓存AOPaopAspectProcessor~150切面处理,动态代理创建Web MVCwebDispatcherServlet~660请求分发,参数绑定,视图解析JDBCjdbcJdbcTemplate~260数据库操作模板,结果映射异常exception4个异常类~110框架异常定义工具utilClassScanner、StringUtils~420类扫描、字符串处理整个框架核心代码约 3800 行,但实现了Spring的核心功能,代码精简而功能完整。
Springwind使用实践

光说不练假把式,下面我们通过两个实际示例来看看SpringWind怎么用。
示例1:User Demo - 完整的用户管理系统

这是一个基于数据库的用户管理系统,展示了SpringWind的IoC、DI、Web MVC和JDBC功能。请从examples里面找到user-demo目录。
项目结构

典型的三层架构:Controller → Service → Dao
  1. user-demo/├── controller/│   └── UserController.java<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />  # 处理HTTP请求├── service/│   └── UserService.java<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />  # 业务逻辑├── dao/│   └── UserDao.java<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />  # 数据访问(使用JdbcTemplate)├── model/│   └── User.java<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /> # 实体类├── config/│   └── DataSourceConfig.java<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /># 数据源配置└── utils/<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />├── ApiResponse.java<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />  # 统一响应封装<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />└── PageResult.java<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />   # 分页结果
复制代码
1. 定义实体类
  1. public class User {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />private Long id;<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private String name;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />private String email;<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />private String phone;<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />private Long createdTime;<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />private Long updatedTime;<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />// getter/setter省略}
复制代码
2. 数据访问层 - 使用JdbcTemplate
  1. @Repositorypublic class UserDao {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@Autowired<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private JdbcTemplate jdbcTemplate;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />// 查询所有用户<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />public List findAll() {<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />return jdbcTemplate.query(<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />"SELECT * FROM users ORDER BY id DESC",<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />this::mapRow<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />);<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />}<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />// 根据ID查询<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />public User findById(Long id) {<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />return jdbcTemplate.queryForObject(<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" /><bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />"SELECT * FROM users WHERE id = ?",<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />this::mapRow,<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" /><bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" />id<bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" /><bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" />);<bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" />}<bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" />// 分页查询<bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" />public List findByPage(int page, int pageSize) {<bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" /><bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" />int offset = (page - 1) * pageSize;<bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" /><bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" />return jdbcTemplate.query(<bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" /><bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" /><bean id="userService" >
  119.     <property name="userDao" ref="userDao"/>
  120. </bean>
  121. <bean id="userDao" />"SELECT * FROM users ORDER BY id DESC LIMIT ? OFFSET ?",<bean id="userService" >
  122.     <property name="userDao" ref="userDao"/>
  123. </bean>
  124. <bean id="userDao" /><bean id="userService" >
  125.     <property name="userDao" ref="userDao"/>
  126. </bean>
  127. <bean id="userDao" /><bean id="userService" >
  128.     <property name="userDao" ref="userDao"/>
  129. </bean>
  130. <bean id="userDao" />this::mapRow,<bean id="userService" >
  131.     <property name="userDao" ref="userDao"/>
  132. </bean>
  133. <bean id="userDao" /><bean id="userService" >
  134.     <property name="userDao" ref="userDao"/>
  135. </bean>
  136. <bean id="userDao" /><bean id="userService" >
  137.     <property name="userDao" ref="userDao"/>
  138. </bean>
  139. <bean id="userDao" />pageSize, offset<bean id="userService" >
  140.     <property name="userDao" ref="userDao"/>
  141. </bean>
  142. <bean id="userDao" /><bean id="userService" >
  143.     <property name="userDao" ref="userDao"/>
  144. </bean>
  145. <bean id="userDao" />);<bean id="userService" >
  146.     <property name="userDao" ref="userDao"/>
  147. </bean>
  148. <bean id="userDao" />}<bean id="userService" >
  149.     <property name="userDao" ref="userDao"/>
  150. </bean>
  151. <bean id="userDao" />// 创建用户<bean id="userService" >
  152.     <property name="userDao" ref="userDao"/>
  153. </bean>
  154. <bean id="userDao" />public int insert(User user) {<bean id="userService" >
  155.     <property name="userDao" ref="userDao"/>
  156. </bean>
  157. <bean id="userDao" /><bean id="userService" >
  158.     <property name="userDao" ref="userDao"/>
  159. </bean>
  160. <bean id="userDao" />return jdbcTemplate.update(<bean id="userService" >
  161.     <property name="userDao" ref="userDao"/>
  162. </bean>
  163. <bean id="userDao" /><bean id="userService" >
  164.     <property name="userDao" ref="userDao"/>
  165. </bean>
  166. <bean id="userDao" /><bean id="userService" >
  167.     <property name="userDao" ref="userDao"/>
  168. </bean>
  169. <bean id="userDao" />"INSERT INTO users (name, email, phone, created_time, updated_time) " +<bean id="userService" >
  170.     <property name="userDao" ref="userDao"/>
  171. </bean>
  172. <bean id="userDao" /><bean id="userService" >
  173.     <property name="userDao" ref="userDao"/>
  174. </bean>
  175. <bean id="userDao" /><bean id="userService" >
  176.     <property name="userDao" ref="userDao"/>
  177. </bean>
  178. <bean id="userDao" />"VALUES (?, ?, ?, ?, ?)",<bean id="userService" >
  179.     <property name="userDao" ref="userDao"/>
  180. </bean>
  181. <bean id="userDao" /><bean id="userService" >
  182.     <property name="userDao" ref="userDao"/>
  183. </bean>
  184. <bean id="userDao" /><bean id="userService" >
  185.     <property name="userDao" ref="userDao"/>
  186. </bean>
  187. <bean id="userDao" />user.getName(), user.getEmail(), user.getPhone(),<bean id="userService" >
  188.     <property name="userDao" ref="userDao"/>
  189. </bean>
  190. <bean id="userDao" /><bean id="userService" >
  191.     <property name="userDao" ref="userDao"/>
  192. </bean>
  193. <bean id="userDao" /><bean id="userService" >
  194.     <property name="userDao" ref="userDao"/>
  195. </bean>
  196. <bean id="userDao" />System.currentTimeMillis(), System.currentTimeMillis()<bean id="userService" >
  197.     <property name="userDao" ref="userDao"/>
  198. </bean>
  199. <bean id="userDao" /><bean id="userService" >
  200.     <property name="userDao" ref="userDao"/>
  201. </bean>
  202. <bean id="userDao" />);<bean id="userService" >
  203.     <property name="userDao" ref="userDao"/>
  204. </bean>
  205. <bean id="userDao" />}<bean id="userService" >
  206.     <property name="userDao" ref="userDao"/>
  207. </bean>
  208. <bean id="userDao" />// 更新用户<bean id="userService" >
  209.     <property name="userDao" ref="userDao"/>
  210. </bean>
  211. <bean id="userDao" />public int update(User user) {<bean id="userService" >
  212.     <property name="userDao" ref="userDao"/>
  213. </bean>
  214. <bean id="userDao" /><bean id="userService" >
  215.     <property name="userDao" ref="userDao"/>
  216. </bean>
  217. <bean id="userDao" />return jdbcTemplate.update(<bean id="userService" >
  218.     <property name="userDao" ref="userDao"/>
  219. </bean>
  220. <bean id="userDao" /><bean id="userService" >
  221.     <property name="userDao" ref="userDao"/>
  222. </bean>
  223. <bean id="userDao" /><bean id="userService" >
  224.     <property name="userDao" ref="userDao"/>
  225. </bean>
  226. <bean id="userDao" />"UPDATE users SET name = ?, email = ?, phone = ?, " +<bean id="userService" >
  227.     <property name="userDao" ref="userDao"/>
  228. </bean>
  229. <bean id="userDao" /><bean id="userService" >
  230.     <property name="userDao" ref="userDao"/>
  231. </bean>
  232. <bean id="userDao" /><bean id="userService" >
  233.     <property name="userDao" ref="userDao"/>
  234. </bean>
  235. <bean id="userDao" />"updated_time = ? WHERE id = ?",<bean id="userService" >
  236.     <property name="userDao" ref="userDao"/>
  237. </bean>
  238. <bean id="userDao" /><bean id="userService" >
  239.     <property name="userDao" ref="userDao"/>
  240. </bean>
  241. <bean id="userDao" /><bean id="userService" >
  242.     <property name="userDao" ref="userDao"/>
  243. </bean>
  244. <bean id="userDao" />user.getName(), user.getEmail(), user.getPhone(),<bean id="userService" >
  245.     <property name="userDao" ref="userDao"/>
  246. </bean>
  247. <bean id="userDao" /><bean id="userService" >
  248.     <property name="userDao" ref="userDao"/>
  249. </bean>
  250. <bean id="userDao" /><bean id="userService" >
  251.     <property name="userDao" ref="userDao"/>
  252. </bean>
  253. <bean id="userDao" />System.currentTimeMillis(), user.getId()<bean id="userService" >
  254.     <property name="userDao" ref="userDao"/>
  255. </bean>
  256. <bean id="userDao" /><bean id="userService" >
  257.     <property name="userDao" ref="userDao"/>
  258. </bean>
  259. <bean id="userDao" />);<bean id="userService" >
  260.     <property name="userDao" ref="userDao"/>
  261. </bean>
  262. <bean id="userDao" />}<bean id="userService" >
  263.     <property name="userDao" ref="userDao"/>
  264. </bean>
  265. <bean id="userDao" />// 删除用户<bean id="userService" >
  266.     <property name="userDao" ref="userDao"/>
  267. </bean>
  268. <bean id="userDao" />public int delete(Long id) {<bean id="userService" >
  269.     <property name="userDao" ref="userDao"/>
  270. </bean>
  271. <bean id="userDao" /><bean id="userService" >
  272.     <property name="userDao" ref="userDao"/>
  273. </bean>
  274. <bean id="userDao" />return jdbcTemplate.update("DELETE FROM users WHERE id = ?", id);<bean id="userService" >
  275.     <property name="userDao" ref="userDao"/>
  276. </bean>
  277. <bean id="userDao" />}<bean id="userService" >
  278.     <property name="userDao" ref="userDao"/>
  279. </bean>
  280. <bean id="userDao" />// 结果集映射<bean id="userService" >
  281.     <property name="userDao" ref="userDao"/>
  282. </bean>
  283. <bean id="userDao" />private User mapRow(ResultSet rs, int rowNum) throws SQLException {<bean id="userService" >
  284.     <property name="userDao" ref="userDao"/>
  285. </bean>
  286. <bean id="userDao" /><bean id="userService" >
  287.     <property name="userDao" ref="userDao"/>
  288. </bean>
  289. <bean id="userDao" />User user = new User();<bean id="userService" >
  290.     <property name="userDao" ref="userDao"/>
  291. </bean>
  292. <bean id="userDao" /><bean id="userService" >
  293.     <property name="userDao" ref="userDao"/>
  294. </bean>
  295. <bean id="userDao" />user.setId(rs.getLong("id"));<bean id="userService" >
  296.     <property name="userDao" ref="userDao"/>
  297. </bean>
  298. <bean id="userDao" /><bean id="userService" >
  299.     <property name="userDao" ref="userDao"/>
  300. </bean>
  301. <bean id="userDao" />user.setName(rs.getString("name"));<bean id="userService" >
  302.     <property name="userDao" ref="userDao"/>
  303. </bean>
  304. <bean id="userDao" /><bean id="userService" >
  305.     <property name="userDao" ref="userDao"/>
  306. </bean>
  307. <bean id="userDao" />user.setEmail(rs.getString("email"));<bean id="userService" >
  308.     <property name="userDao" ref="userDao"/>
  309. </bean>
  310. <bean id="userDao" /><bean id="userService" >
  311.     <property name="userDao" ref="userDao"/>
  312. </bean>
  313. <bean id="userDao" />user.setPhone(rs.getString("phone"));<bean id="userService" >
  314.     <property name="userDao" ref="userDao"/>
  315. </bean>
  316. <bean id="userDao" /><bean id="userService" >
  317.     <property name="userDao" ref="userDao"/>
  318. </bean>
  319. <bean id="userDao" />user.setCreatedTime(rs.getLong("created_time"));<bean id="userService" >
  320.     <property name="userDao" ref="userDao"/>
  321. </bean>
  322. <bean id="userDao" /><bean id="userService" >
  323.     <property name="userDao" ref="userDao"/>
  324. </bean>
  325. <bean id="userDao" />user.setUpdatedTime(rs.getLong("updated_time"));<bean id="userService" >
  326.     <property name="userDao" ref="userDao"/>
  327. </bean>
  328. <bean id="userDao" /><bean id="userService" >
  329.     <property name="userDao" ref="userDao"/>
  330. </bean>
  331. <bean id="userDao" />return user;<bean id="userService" >
  332.     <property name="userDao" ref="userDao"/>
  333. </bean>
  334. <bean id="userDao" />}}
复制代码
看到了吗? 原本50多行的JDBC代码,现在只需要2行。JdbcTemplate自动处理了连接管理、资源关闭、异常处理。
3. 服务层 - 业务逻辑
  1. @Servicepublic class UserService {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@Autowired<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private UserDao userDao;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />public List getAllUsers() {<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />return userDao.findAll();<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />}<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />public User getUserById(Long id) {<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />return userDao.findById(id);<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />}<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />public List getUsersByPage(int page, int pageSize) {<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />return userDao.findByPage(page, pageSize);<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />}<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />public Long getUserCount() {<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />return userDao.count();<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" />}<bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />public boolean createUser(User user) {<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />return userDao.insert(user) > 0;<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />}<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" />public boolean updateUser(User user) {<bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />return userDao.update(user) > 0;<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" />}<bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" />public boolean deleteUser(Long id) {<bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" /><bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" />return userDao.delete(id) > 0;<bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" />}}
复制代码
服务层很薄,主要是调用Dao层。如果有复杂的业务逻辑(比如用户注册需要发送邮件),就写在这里。
4. 控制器层 - RESTful API
  1. @Controller@RequestMapping("/user")public class UserController {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@Autowired<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private UserService userService;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />// 获取用户列表(支持分页)<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />@RequestMapping("/list")<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />@ResponseBody<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />public ViewResult list(HttpServletRequest request) {<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />try {<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />String pageStr = request.getParameter("page");<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />String pageSizeStr = request.getParameter("pageSize");<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />if (pageStr != null && pageSizeStr != null) {<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" /><bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />// 分页查询<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" /><bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />int page = Integer.parseInt(pageStr);<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" /><bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" /><bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" />int pageSize = Integer.parseInt(pageSizeStr);<bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" /><bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" /><bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" /><bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" />List users = userService.getUsersByPage(page, pageSize);<bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" /><bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" /><bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" /><bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" />Long total = userService.getUserCount();<bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" /><bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" /><bean id="userService" >
  119.     <property name="userDao" ref="userDao"/>
  120. </bean>
  121. <bean id="userDao" /><bean id="userService" >
  122.     <property name="userDao" ref="userDao"/>
  123. </bean>
  124. <bean id="userDao" />// 使用PageResult和ApiResponse简化响应构建<bean id="userService" >
  125.     <property name="userDao" ref="userDao"/>
  126. </bean>
  127. <bean id="userDao" /><bean id="userService" >
  128.     <property name="userDao" ref="userDao"/>
  129. </bean>
  130. <bean id="userDao" /><bean id="userService" >
  131.     <property name="userDao" ref="userDao"/>
  132. </bean>
  133. <bean id="userDao" /><bean id="userService" >
  134.     <property name="userDao" ref="userDao"/>
  135. </bean>
  136. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  137.     <property name="userDao" ref="userDao"/>
  138. </bean>
  139. <bean id="userDao" /><bean id="userService" >
  140.     <property name="userDao" ref="userDao"/>
  141. </bean>
  142. <bean id="userDao" /><bean id="userService" >
  143.     <property name="userDao" ref="userDao"/>
  144. </bean>
  145. <bean id="userDao" /><bean id="userService" >
  146.     <property name="userDao" ref="userDao"/>
  147. </bean>
  148. <bean id="userDao" /><bean id="userService" >
  149.     <property name="userDao" ref="userDao"/>
  150. </bean>
  151. <bean id="userDao" />ApiResponse.page(users, page, pageSize, total).toMap()<bean id="userService" >
  152.     <property name="userDao" ref="userDao"/>
  153. </bean>
  154. <bean id="userDao" /><bean id="userService" >
  155.     <property name="userDao" ref="userDao"/>
  156. </bean>
  157. <bean id="userDao" /><bean id="userService" >
  158.     <property name="userDao" ref="userDao"/>
  159. </bean>
  160. <bean id="userDao" /><bean id="userService" >
  161.     <property name="userDao" ref="userDao"/>
  162. </bean>
  163. <bean id="userDao" />);<bean id="userService" >
  164.     <property name="userDao" ref="userDao"/>
  165. </bean>
  166. <bean id="userDao" /><bean id="userService" >
  167.     <property name="userDao" ref="userDao"/>
  168. </bean>
  169. <bean id="userDao" /><bean id="userService" >
  170.     <property name="userDao" ref="userDao"/>
  171. </bean>
  172. <bean id="userDao" />} else {<bean id="userService" >
  173.     <property name="userDao" ref="userDao"/>
  174. </bean>
  175. <bean id="userDao" /><bean id="userService" >
  176.     <property name="userDao" ref="userDao"/>
  177. </bean>
  178. <bean id="userDao" /><bean id="userService" >
  179.     <property name="userDao" ref="userDao"/>
  180. </bean>
  181. <bean id="userDao" /><bean id="userService" >
  182.     <property name="userDao" ref="userDao"/>
  183. </bean>
  184. <bean id="userDao" />// 查询所有<bean id="userService" >
  185.     <property name="userDao" ref="userDao"/>
  186. </bean>
  187. <bean id="userDao" /><bean id="userService" >
  188.     <property name="userDao" ref="userDao"/>
  189. </bean>
  190. <bean id="userDao" /><bean id="userService" >
  191.     <property name="userDao" ref="userDao"/>
  192. </bean>
  193. <bean id="userDao" /><bean id="userService" >
  194.     <property name="userDao" ref="userDao"/>
  195. </bean>
  196. <bean id="userDao" />List users = userService.getAllUsers();<bean id="userService" >
  197.     <property name="userDao" ref="userDao"/>
  198. </bean>
  199. <bean id="userDao" /><bean id="userService" >
  200.     <property name="userDao" ref="userDao"/>
  201. </bean>
  202. <bean id="userDao" /><bean id="userService" >
  203.     <property name="userDao" ref="userDao"/>
  204. </bean>
  205. <bean id="userDao" /><bean id="userService" >
  206.     <property name="userDao" ref="userDao"/>
  207. </bean>
  208. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  209.     <property name="userDao" ref="userDao"/>
  210. </bean>
  211. <bean id="userDao" /><bean id="userService" >
  212.     <property name="userDao" ref="userDao"/>
  213. </bean>
  214. <bean id="userDao" /><bean id="userService" >
  215.     <property name="userDao" ref="userDao"/>
  216. </bean>
  217. <bean id="userDao" /><bean id="userService" >
  218.     <property name="userDao" ref="userDao"/>
  219. </bean>
  220. <bean id="userDao" /><bean id="userService" >
  221.     <property name="userDao" ref="userDao"/>
  222. </bean>
  223. <bean id="userDao" />ApiResponse.success(users, "获取用户列表成功").toMap()<bean id="userService" >
  224.     <property name="userDao" ref="userDao"/>
  225. </bean>
  226. <bean id="userDao" /><bean id="userService" >
  227.     <property name="userDao" ref="userDao"/>
  228. </bean>
  229. <bean id="userDao" /><bean id="userService" >
  230.     <property name="userDao" ref="userDao"/>
  231. </bean>
  232. <bean id="userDao" /><bean id="userService" >
  233.     <property name="userDao" ref="userDao"/>
  234. </bean>
  235. <bean id="userDao" />);<bean id="userService" >
  236.     <property name="userDao" ref="userDao"/>
  237. </bean>
  238. <bean id="userDao" /><bean id="userService" >
  239.     <property name="userDao" ref="userDao"/>
  240. </bean>
  241. <bean id="userDao" /><bean id="userService" >
  242.     <property name="userDao" ref="userDao"/>
  243. </bean>
  244. <bean id="userDao" />}<bean id="userService" >
  245.     <property name="userDao" ref="userDao"/>
  246. </bean>
  247. <bean id="userDao" /><bean id="userService" >
  248.     <property name="userDao" ref="userDao"/>
  249. </bean>
  250. <bean id="userDao" />} catch (Exception e) {<bean id="userService" >
  251.     <property name="userDao" ref="userDao"/>
  252. </bean>
  253. <bean id="userDao" /><bean id="userService" >
  254.     <property name="userDao" ref="userDao"/>
  255. </bean>
  256. <bean id="userDao" /><bean id="userService" >
  257.     <property name="userDao" ref="userDao"/>
  258. </bean>
  259. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  260.     <property name="userDao" ref="userDao"/>
  261. </bean>
  262. <bean id="userDao" /><bean id="userService" >
  263.     <property name="userDao" ref="userDao"/>
  264. </bean>
  265. <bean id="userDao" /><bean id="userService" >
  266.     <property name="userDao" ref="userDao"/>
  267. </bean>
  268. <bean id="userDao" /><bean id="userService" >
  269.     <property name="userDao" ref="userDao"/>
  270. </bean>
  271. <bean id="userDao" />ApiResponse.failure("获取用户列表失败: " + e.getMessage()).toMap()<bean id="userService" >
  272.     <property name="userDao" ref="userDao"/>
  273. </bean>
  274. <bean id="userDao" /><bean id="userService" >
  275.     <property name="userDao" ref="userDao"/>
  276. </bean>
  277. <bean id="userDao" /><bean id="userService" >
  278.     <property name="userDao" ref="userDao"/>
  279. </bean>
  280. <bean id="userDao" />);<bean id="userService" >
  281.     <property name="userDao" ref="userDao"/>
  282. </bean>
  283. <bean id="userDao" /><bean id="userService" >
  284.     <property name="userDao" ref="userDao"/>
  285. </bean>
  286. <bean id="userDao" />}<bean id="userService" >
  287.     <property name="userDao" ref="userDao"/>
  288. </bean>
  289. <bean id="userDao" />}<bean id="userService" >
  290.     <property name="userDao" ref="userDao"/>
  291. </bean>
  292. <bean id="userDao" />// 获取单个用户<bean id="userService" >
  293.     <property name="userDao" ref="userDao"/>
  294. </bean>
  295. <bean id="userDao" />@RequestMapping("/get")<bean id="userService" >
  296.     <property name="userDao" ref="userDao"/>
  297. </bean>
  298. <bean id="userDao" />@ResponseBody<bean id="userService" >
  299.     <property name="userDao" ref="userDao"/>
  300. </bean>
  301. <bean id="userDao" />public ViewResult getById(HttpServletRequest request) {<bean id="userService" >
  302.     <property name="userDao" ref="userDao"/>
  303. </bean>
  304. <bean id="userDao" /><bean id="userService" >
  305.     <property name="userDao" ref="userDao"/>
  306. </bean>
  307. <bean id="userDao" />try {<bean id="userService" >
  308.     <property name="userDao" ref="userDao"/>
  309. </bean>
  310. <bean id="userDao" /><bean id="userService" >
  311.     <property name="userDao" ref="userDao"/>
  312. </bean>
  313. <bean id="userDao" /><bean id="userService" >
  314.     <property name="userDao" ref="userDao"/>
  315. </bean>
  316. <bean id="userDao" />String idStr = request.getParameter("id");<bean id="userService" >
  317.     <property name="userDao" ref="userDao"/>
  318. </bean>
  319. <bean id="userDao" /><bean id="userService" >
  320.     <property name="userDao" ref="userDao"/>
  321. </bean>
  322. <bean id="userDao" /><bean id="userService" >
  323.     <property name="userDao" ref="userDao"/>
  324. </bean>
  325. <bean id="userDao" />if (idStr == null || idStr.isEmpty()) {<bean id="userService" >
  326.     <property name="userDao" ref="userDao"/>
  327. </bean>
  328. <bean id="userDao" /><bean id="userService" >
  329.     <property name="userDao" ref="userDao"/>
  330. </bean>
  331. <bean id="userDao" /><bean id="userService" >
  332.     <property name="userDao" ref="userDao"/>
  333. </bean>
  334. <bean id="userDao" /><bean id="userService" >
  335.     <property name="userDao" ref="userDao"/>
  336. </bean>
  337. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  338.     <property name="userDao" ref="userDao"/>
  339. </bean>
  340. <bean id="userDao" /><bean id="userService" >
  341.     <property name="userDao" ref="userDao"/>
  342. </bean>
  343. <bean id="userDao" /><bean id="userService" >
  344.     <property name="userDao" ref="userDao"/>
  345. </bean>
  346. <bean id="userDao" /><bean id="userService" >
  347.     <property name="userDao" ref="userDao"/>
  348. </bean>
  349. <bean id="userDao" /><bean id="userService" >
  350.     <property name="userDao" ref="userDao"/>
  351. </bean>
  352. <bean id="userDao" />ApiResponse.badRequest("用户ID不能为空").toMap()<bean id="userService" >
  353.     <property name="userDao" ref="userDao"/>
  354. </bean>
  355. <bean id="userDao" /><bean id="userService" >
  356.     <property name="userDao" ref="userDao"/>
  357. </bean>
  358. <bean id="userDao" /><bean id="userService" >
  359.     <property name="userDao" ref="userDao"/>
  360. </bean>
  361. <bean id="userDao" /><bean id="userService" >
  362.     <property name="userDao" ref="userDao"/>
  363. </bean>
  364. <bean id="userDao" />);<bean id="userService" >
  365.     <property name="userDao" ref="userDao"/>
  366. </bean>
  367. <bean id="userDao" /><bean id="userService" >
  368.     <property name="userDao" ref="userDao"/>
  369. </bean>
  370. <bean id="userDao" /><bean id="userService" >
  371.     <property name="userDao" ref="userDao"/>
  372. </bean>
  373. <bean id="userDao" />}<bean id="userService" >
  374.     <property name="userDao" ref="userDao"/>
  375. </bean>
  376. <bean id="userDao" /><bean id="userService" >
  377.     <property name="userDao" ref="userDao"/>
  378. </bean>
  379. <bean id="userDao" /><bean id="userService" >
  380.     <property name="userDao" ref="userDao"/>
  381. </bean>
  382. <bean id="userDao" />Long id = Long.parseLong(idStr);<bean id="userService" >
  383.     <property name="userDao" ref="userDao"/>
  384. </bean>
  385. <bean id="userDao" /><bean id="userService" >
  386.     <property name="userDao" ref="userDao"/>
  387. </bean>
  388. <bean id="userDao" /><bean id="userService" >
  389.     <property name="userDao" ref="userDao"/>
  390. </bean>
  391. <bean id="userDao" />User user = userService.getUserById(id);<bean id="userService" >
  392.     <property name="userDao" ref="userDao"/>
  393. </bean>
  394. <bean id="userDao" /><bean id="userService" >
  395.     <property name="userDao" ref="userDao"/>
  396. </bean>
  397. <bean id="userDao" /><bean id="userService" >
  398.     <property name="userDao" ref="userDao"/>
  399. </bean>
  400. <bean id="userDao" />if (user == null) {<bean id="userService" >
  401.     <property name="userDao" ref="userDao"/>
  402. </bean>
  403. <bean id="userDao" /><bean id="userService" >
  404.     <property name="userDao" ref="userDao"/>
  405. </bean>
  406. <bean id="userDao" /><bean id="userService" >
  407.     <property name="userDao" ref="userDao"/>
  408. </bean>
  409. <bean id="userDao" /><bean id="userService" >
  410.     <property name="userDao" ref="userDao"/>
  411. </bean>
  412. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  413.     <property name="userDao" ref="userDao"/>
  414. </bean>
  415. <bean id="userDao" /><bean id="userService" >
  416.     <property name="userDao" ref="userDao"/>
  417. </bean>
  418. <bean id="userDao" /><bean id="userService" >
  419.     <property name="userDao" ref="userDao"/>
  420. </bean>
  421. <bean id="userDao" /><bean id="userService" >
  422.     <property name="userDao" ref="userDao"/>
  423. </bean>
  424. <bean id="userDao" /><bean id="userService" >
  425.     <property name="userDao" ref="userDao"/>
  426. </bean>
  427. <bean id="userDao" />ApiResponse.notFound("用户不存在").toMap()<bean id="userService" >
  428.     <property name="userDao" ref="userDao"/>
  429. </bean>
  430. <bean id="userDao" /><bean id="userService" >
  431.     <property name="userDao" ref="userDao"/>
  432. </bean>
  433. <bean id="userDao" /><bean id="userService" >
  434.     <property name="userDao" ref="userDao"/>
  435. </bean>
  436. <bean id="userDao" /><bean id="userService" >
  437.     <property name="userDao" ref="userDao"/>
  438. </bean>
  439. <bean id="userDao" />);<bean id="userService" >
  440.     <property name="userDao" ref="userDao"/>
  441. </bean>
  442. <bean id="userDao" /><bean id="userService" >
  443.     <property name="userDao" ref="userDao"/>
  444. </bean>
  445. <bean id="userDao" /><bean id="userService" >
  446.     <property name="userDao" ref="userDao"/>
  447. </bean>
  448. <bean id="userDao" />}<bean id="userService" >
  449.     <property name="userDao" ref="userDao"/>
  450. </bean>
  451. <bean id="userDao" /><bean id="userService" >
  452.     <property name="userDao" ref="userDao"/>
  453. </bean>
  454. <bean id="userDao" /><bean id="userService" >
  455.     <property name="userDao" ref="userDao"/>
  456. </bean>
  457. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  458.     <property name="userDao" ref="userDao"/>
  459. </bean>
  460. <bean id="userDao" /><bean id="userService" >
  461.     <property name="userDao" ref="userDao"/>
  462. </bean>
  463. <bean id="userDao" /><bean id="userService" >
  464.     <property name="userDao" ref="userDao"/>
  465. </bean>
  466. <bean id="userDao" /><bean id="userService" >
  467.     <property name="userDao" ref="userDao"/>
  468. </bean>
  469. <bean id="userDao" />ApiResponse.success(user, "获取用户详情成功").toMap()<bean id="userService" >
  470.     <property name="userDao" ref="userDao"/>
  471. </bean>
  472. <bean id="userDao" /><bean id="userService" >
  473.     <property name="userDao" ref="userDao"/>
  474. </bean>
  475. <bean id="userDao" /><bean id="userService" >
  476.     <property name="userDao" ref="userDao"/>
  477. </bean>
  478. <bean id="userDao" />);<bean id="userService" >
  479.     <property name="userDao" ref="userDao"/>
  480. </bean>
  481. <bean id="userDao" /><bean id="userService" >
  482.     <property name="userDao" ref="userDao"/>
  483. </bean>
  484. <bean id="userDao" />} catch (Exception e) {<bean id="userService" >
  485.     <property name="userDao" ref="userDao"/>
  486. </bean>
  487. <bean id="userDao" /><bean id="userService" >
  488.     <property name="userDao" ref="userDao"/>
  489. </bean>
  490. <bean id="userDao" /><bean id="userService" >
  491.     <property name="userDao" ref="userDao"/>
  492. </bean>
  493. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  494.     <property name="userDao" ref="userDao"/>
  495. </bean>
  496. <bean id="userDao" /><bean id="userService" >
  497.     <property name="userDao" ref="userDao"/>
  498. </bean>
  499. <bean id="userDao" /><bean id="userService" >
  500.     <property name="userDao" ref="userDao"/>
  501. </bean>
  502. <bean id="userDao" /><bean id="userService" >
  503.     <property name="userDao" ref="userDao"/>
  504. </bean>
  505. <bean id="userDao" />ApiResponse.failure("获取用户失败: " + e.getMessage()).toMap()<bean id="userService" >
  506.     <property name="userDao" ref="userDao"/>
  507. </bean>
  508. <bean id="userDao" /><bean id="userService" >
  509.     <property name="userDao" ref="userDao"/>
  510. </bean>
  511. <bean id="userDao" /><bean id="userService" >
  512.     <property name="userDao" ref="userDao"/>
  513. </bean>
  514. <bean id="userDao" />);<bean id="userService" >
  515.     <property name="userDao" ref="userDao"/>
  516. </bean>
  517. <bean id="userDao" /><bean id="userService" >
  518.     <property name="userDao" ref="userDao"/>
  519. </bean>
  520. <bean id="userDao" />}<bean id="userService" >
  521.     <property name="userDao" ref="userDao"/>
  522. </bean>
  523. <bean id="userDao" />}<bean id="userService" >
  524.     <property name="userDao" ref="userDao"/>
  525. </bean>
  526. <bean id="userDao" />// 创建用户<bean id="userService" >
  527.     <property name="userDao" ref="userDao"/>
  528. </bean>
  529. <bean id="userDao" />@RequestMapping("/create")<bean id="userService" >
  530.     <property name="userDao" ref="userDao"/>
  531. </bean>
  532. <bean id="userDao" />@ResponseBody<bean id="userService" >
  533.     <property name="userDao" ref="userDao"/>
  534. </bean>
  535. <bean id="userDao" />public ViewResult create(@RequestBody User user) {<bean id="userService" >
  536.     <property name="userDao" ref="userDao"/>
  537. </bean>
  538. <bean id="userDao" /><bean id="userService" >
  539.     <property name="userDao" ref="userDao"/>
  540. </bean>
  541. <bean id="userDao" />try {<bean id="userService" >
  542.     <property name="userDao" ref="userDao"/>
  543. </bean>
  544. <bean id="userDao" /><bean id="userService" >
  545.     <property name="userDao" ref="userDao"/>
  546. </bean>
  547. <bean id="userDao" /><bean id="userService" >
  548.     <property name="userDao" ref="userDao"/>
  549. </bean>
  550. <bean id="userDao" />boolean success = userService.createUser(user);<bean id="userService" >
  551.     <property name="userDao" ref="userDao"/>
  552. </bean>
  553. <bean id="userDao" /><bean id="userService" >
  554.     <property name="userDao" ref="userDao"/>
  555. </bean>
  556. <bean id="userDao" /><bean id="userService" >
  557.     <property name="userDao" ref="userDao"/>
  558. </bean>
  559. <bean id="userDao" />if (success) {<bean id="userService" >
  560.     <property name="userDao" ref="userDao"/>
  561. </bean>
  562. <bean id="userDao" /><bean id="userService" >
  563.     <property name="userDao" ref="userDao"/>
  564. </bean>
  565. <bean id="userDao" /><bean id="userService" >
  566.     <property name="userDao" ref="userDao"/>
  567. </bean>
  568. <bean id="userDao" /><bean id="userService" >
  569.     <property name="userDao" ref="userDao"/>
  570. </bean>
  571. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  572.     <property name="userDao" ref="userDao"/>
  573. </bean>
  574. <bean id="userDao" /><bean id="userService" >
  575.     <property name="userDao" ref="userDao"/>
  576. </bean>
  577. <bean id="userDao" /><bean id="userService" >
  578.     <property name="userDao" ref="userDao"/>
  579. </bean>
  580. <bean id="userDao" /><bean id="userService" >
  581.     <property name="userDao" ref="userDao"/>
  582. </bean>
  583. <bean id="userDao" /><bean id="userService" >
  584.     <property name="userDao" ref="userDao"/>
  585. </bean>
  586. <bean id="userDao" />ApiResponse.success(user, "创建用户成功").toMap()<bean id="userService" >
  587.     <property name="userDao" ref="userDao"/>
  588. </bean>
  589. <bean id="userDao" /><bean id="userService" >
  590.     <property name="userDao" ref="userDao"/>
  591. </bean>
  592. <bean id="userDao" /><bean id="userService" >
  593.     <property name="userDao" ref="userDao"/>
  594. </bean>
  595. <bean id="userDao" /><bean id="userService" >
  596.     <property name="userDao" ref="userDao"/>
  597. </bean>
  598. <bean id="userDao" />);<bean id="userService" >
  599.     <property name="userDao" ref="userDao"/>
  600. </bean>
  601. <bean id="userDao" /><bean id="userService" >
  602.     <property name="userDao" ref="userDao"/>
  603. </bean>
  604. <bean id="userDao" /><bean id="userService" >
  605.     <property name="userDao" ref="userDao"/>
  606. </bean>
  607. <bean id="userDao" />} else {<bean id="userService" >
  608.     <property name="userDao" ref="userDao"/>
  609. </bean>
  610. <bean id="userDao" /><bean id="userService" >
  611.     <property name="userDao" ref="userDao"/>
  612. </bean>
  613. <bean id="userDao" /><bean id="userService" >
  614.     <property name="userDao" ref="userDao"/>
  615. </bean>
  616. <bean id="userDao" /><bean id="userService" >
  617.     <property name="userDao" ref="userDao"/>
  618. </bean>
  619. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  620.     <property name="userDao" ref="userDao"/>
  621. </bean>
  622. <bean id="userDao" /><bean id="userService" >
  623.     <property name="userDao" ref="userDao"/>
  624. </bean>
  625. <bean id="userDao" /><bean id="userService" >
  626.     <property name="userDao" ref="userDao"/>
  627. </bean>
  628. <bean id="userDao" /><bean id="userService" >
  629.     <property name="userDao" ref="userDao"/>
  630. </bean>
  631. <bean id="userDao" /><bean id="userService" >
  632.     <property name="userDao" ref="userDao"/>
  633. </bean>
  634. <bean id="userDao" />ApiResponse.failure("创建用户失败").toMap()<bean id="userService" >
  635.     <property name="userDao" ref="userDao"/>
  636. </bean>
  637. <bean id="userDao" /><bean id="userService" >
  638.     <property name="userDao" ref="userDao"/>
  639. </bean>
  640. <bean id="userDao" /><bean id="userService" >
  641.     <property name="userDao" ref="userDao"/>
  642. </bean>
  643. <bean id="userDao" /><bean id="userService" >
  644.     <property name="userDao" ref="userDao"/>
  645. </bean>
  646. <bean id="userDao" />);<bean id="userService" >
  647.     <property name="userDao" ref="userDao"/>
  648. </bean>
  649. <bean id="userDao" /><bean id="userService" >
  650.     <property name="userDao" ref="userDao"/>
  651. </bean>
  652. <bean id="userDao" /><bean id="userService" >
  653.     <property name="userDao" ref="userDao"/>
  654. </bean>
  655. <bean id="userDao" />}<bean id="userService" >
  656.     <property name="userDao" ref="userDao"/>
  657. </bean>
  658. <bean id="userDao" /><bean id="userService" >
  659.     <property name="userDao" ref="userDao"/>
  660. </bean>
  661. <bean id="userDao" />} catch (Exception e) {<bean id="userService" >
  662.     <property name="userDao" ref="userDao"/>
  663. </bean>
  664. <bean id="userDao" /><bean id="userService" >
  665.     <property name="userDao" ref="userDao"/>
  666. </bean>
  667. <bean id="userDao" /><bean id="userService" >
  668.     <property name="userDao" ref="userDao"/>
  669. </bean>
  670. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  671.     <property name="userDao" ref="userDao"/>
  672. </bean>
  673. <bean id="userDao" /><bean id="userService" >
  674.     <property name="userDao" ref="userDao"/>
  675. </bean>
  676. <bean id="userDao" /><bean id="userService" >
  677.     <property name="userDao" ref="userDao"/>
  678. </bean>
  679. <bean id="userDao" /><bean id="userService" >
  680.     <property name="userDao" ref="userDao"/>
  681. </bean>
  682. <bean id="userDao" />ApiResponse.failure("创建用户失败: " + e.getMessage()).toMap()<bean id="userService" >
  683.     <property name="userDao" ref="userDao"/>
  684. </bean>
  685. <bean id="userDao" /><bean id="userService" >
  686.     <property name="userDao" ref="userDao"/>
  687. </bean>
  688. <bean id="userDao" /><bean id="userService" >
  689.     <property name="userDao" ref="userDao"/>
  690. </bean>
  691. <bean id="userDao" />);<bean id="userService" >
  692.     <property name="userDao" ref="userDao"/>
  693. </bean>
  694. <bean id="userDao" /><bean id="userService" >
  695.     <property name="userDao" ref="userDao"/>
  696. </bean>
  697. <bean id="userDao" />}<bean id="userService" >
  698.     <property name="userDao" ref="userDao"/>
  699. </bean>
  700. <bean id="userDao" />}<bean id="userService" >
  701.     <property name="userDao" ref="userDao"/>
  702. </bean>
  703. <bean id="userDao" />// 更新用户<bean id="userService" >
  704.     <property name="userDao" ref="userDao"/>
  705. </bean>
  706. <bean id="userDao" />@RequestMapping("/update")<bean id="userService" >
  707.     <property name="userDao" ref="userDao"/>
  708. </bean>
  709. <bean id="userDao" />@ResponseBody<bean id="userService" >
  710.     <property name="userDao" ref="userDao"/>
  711. </bean>
  712. <bean id="userDao" />public ViewResult update(@RequestBody User user) {<bean id="userService" >
  713.     <property name="userDao" ref="userDao"/>
  714. </bean>
  715. <bean id="userDao" /><bean id="userService" >
  716.     <property name="userDao" ref="userDao"/>
  717. </bean>
  718. <bean id="userDao" />try {<bean id="userService" >
  719.     <property name="userDao" ref="userDao"/>
  720. </bean>
  721. <bean id="userDao" /><bean id="userService" >
  722.     <property name="userDao" ref="userDao"/>
  723. </bean>
  724. <bean id="userDao" /><bean id="userService" >
  725.     <property name="userDao" ref="userDao"/>
  726. </bean>
  727. <bean id="userDao" />boolean success = userService.updateUser(user);<bean id="userService" >
  728.     <property name="userDao" ref="userDao"/>
  729. </bean>
  730. <bean id="userDao" /><bean id="userService" >
  731.     <property name="userDao" ref="userDao"/>
  732. </bean>
  733. <bean id="userDao" /><bean id="userService" >
  734.     <property name="userDao" ref="userDao"/>
  735. </bean>
  736. <bean id="userDao" />if (success) {<bean id="userService" >
  737.     <property name="userDao" ref="userDao"/>
  738. </bean>
  739. <bean id="userDao" /><bean id="userService" >
  740.     <property name="userDao" ref="userDao"/>
  741. </bean>
  742. <bean id="userDao" /><bean id="userService" >
  743.     <property name="userDao" ref="userDao"/>
  744. </bean>
  745. <bean id="userDao" /><bean id="userService" >
  746.     <property name="userDao" ref="userDao"/>
  747. </bean>
  748. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  749.     <property name="userDao" ref="userDao"/>
  750. </bean>
  751. <bean id="userDao" /><bean id="userService" >
  752.     <property name="userDao" ref="userDao"/>
  753. </bean>
  754. <bean id="userDao" /><bean id="userService" >
  755.     <property name="userDao" ref="userDao"/>
  756. </bean>
  757. <bean id="userDao" /><bean id="userService" >
  758.     <property name="userDao" ref="userDao"/>
  759. </bean>
  760. <bean id="userDao" /><bean id="userService" >
  761.     <property name="userDao" ref="userDao"/>
  762. </bean>
  763. <bean id="userDao" />ApiResponse.success(user, "更新用户成功").toMap()<bean id="userService" >
  764.     <property name="userDao" ref="userDao"/>
  765. </bean>
  766. <bean id="userDao" /><bean id="userService" >
  767.     <property name="userDao" ref="userDao"/>
  768. </bean>
  769. <bean id="userDao" /><bean id="userService" >
  770.     <property name="userDao" ref="userDao"/>
  771. </bean>
  772. <bean id="userDao" /><bean id="userService" >
  773.     <property name="userDao" ref="userDao"/>
  774. </bean>
  775. <bean id="userDao" />);<bean id="userService" >
  776.     <property name="userDao" ref="userDao"/>
  777. </bean>
  778. <bean id="userDao" /><bean id="userService" >
  779.     <property name="userDao" ref="userDao"/>
  780. </bean>
  781. <bean id="userDao" /><bean id="userService" >
  782.     <property name="userDao" ref="userDao"/>
  783. </bean>
  784. <bean id="userDao" />} else {<bean id="userService" >
  785.     <property name="userDao" ref="userDao"/>
  786. </bean>
  787. <bean id="userDao" /><bean id="userService" >
  788.     <property name="userDao" ref="userDao"/>
  789. </bean>
  790. <bean id="userDao" /><bean id="userService" >
  791.     <property name="userDao" ref="userDao"/>
  792. </bean>
  793. <bean id="userDao" /><bean id="userService" >
  794.     <property name="userDao" ref="userDao"/>
  795. </bean>
  796. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  797.     <property name="userDao" ref="userDao"/>
  798. </bean>
  799. <bean id="userDao" /><bean id="userService" >
  800.     <property name="userDao" ref="userDao"/>
  801. </bean>
  802. <bean id="userDao" /><bean id="userService" >
  803.     <property name="userDao" ref="userDao"/>
  804. </bean>
  805. <bean id="userDao" /><bean id="userService" >
  806.     <property name="userDao" ref="userDao"/>
  807. </bean>
  808. <bean id="userDao" /><bean id="userService" >
  809.     <property name="userDao" ref="userDao"/>
  810. </bean>
  811. <bean id="userDao" />ApiResponse.failure("更新用户失败").toMap()<bean id="userService" >
  812.     <property name="userDao" ref="userDao"/>
  813. </bean>
  814. <bean id="userDao" /><bean id="userService" >
  815.     <property name="userDao" ref="userDao"/>
  816. </bean>
  817. <bean id="userDao" /><bean id="userService" >
  818.     <property name="userDao" ref="userDao"/>
  819. </bean>
  820. <bean id="userDao" /><bean id="userService" >
  821.     <property name="userDao" ref="userDao"/>
  822. </bean>
  823. <bean id="userDao" />);<bean id="userService" >
  824.     <property name="userDao" ref="userDao"/>
  825. </bean>
  826. <bean id="userDao" /><bean id="userService" >
  827.     <property name="userDao" ref="userDao"/>
  828. </bean>
  829. <bean id="userDao" /><bean id="userService" >
  830.     <property name="userDao" ref="userDao"/>
  831. </bean>
  832. <bean id="userDao" />}<bean id="userService" >
  833.     <property name="userDao" ref="userDao"/>
  834. </bean>
  835. <bean id="userDao" /><bean id="userService" >
  836.     <property name="userDao" ref="userDao"/>
  837. </bean>
  838. <bean id="userDao" />} catch (Exception e) {<bean id="userService" >
  839.     <property name="userDao" ref="userDao"/>
  840. </bean>
  841. <bean id="userDao" /><bean id="userService" >
  842.     <property name="userDao" ref="userDao"/>
  843. </bean>
  844. <bean id="userDao" /><bean id="userService" >
  845.     <property name="userDao" ref="userDao"/>
  846. </bean>
  847. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  848.     <property name="userDao" ref="userDao"/>
  849. </bean>
  850. <bean id="userDao" /><bean id="userService" >
  851.     <property name="userDao" ref="userDao"/>
  852. </bean>
  853. <bean id="userDao" /><bean id="userService" >
  854.     <property name="userDao" ref="userDao"/>
  855. </bean>
  856. <bean id="userDao" /><bean id="userService" >
  857.     <property name="userDao" ref="userDao"/>
  858. </bean>
  859. <bean id="userDao" />ApiResponse.failure("更新用户失败: " + e.getMessage()).toMap()<bean id="userService" >
  860.     <property name="userDao" ref="userDao"/>
  861. </bean>
  862. <bean id="userDao" /><bean id="userService" >
  863.     <property name="userDao" ref="userDao"/>
  864. </bean>
  865. <bean id="userDao" /><bean id="userService" >
  866.     <property name="userDao" ref="userDao"/>
  867. </bean>
  868. <bean id="userDao" />);<bean id="userService" >
  869.     <property name="userDao" ref="userDao"/>
  870. </bean>
  871. <bean id="userDao" /><bean id="userService" >
  872.     <property name="userDao" ref="userDao"/>
  873. </bean>
  874. <bean id="userDao" />}<bean id="userService" >
  875.     <property name="userDao" ref="userDao"/>
  876. </bean>
  877. <bean id="userDao" />}<bean id="userService" >
  878.     <property name="userDao" ref="userDao"/>
  879. </bean>
  880. <bean id="userDao" />// 删除用户<bean id="userService" >
  881.     <property name="userDao" ref="userDao"/>
  882. </bean>
  883. <bean id="userDao" />@RequestMapping("/delete")<bean id="userService" >
  884.     <property name="userDao" ref="userDao"/>
  885. </bean>
  886. <bean id="userDao" />@ResponseBody<bean id="userService" >
  887.     <property name="userDao" ref="userDao"/>
  888. </bean>
  889. <bean id="userDao" />public ViewResult delete(HttpServletRequest request) {<bean id="userService" >
  890.     <property name="userDao" ref="userDao"/>
  891. </bean>
  892. <bean id="userDao" /><bean id="userService" >
  893.     <property name="userDao" ref="userDao"/>
  894. </bean>
  895. <bean id="userDao" />try {<bean id="userService" >
  896.     <property name="userDao" ref="userDao"/>
  897. </bean>
  898. <bean id="userDao" /><bean id="userService" >
  899.     <property name="userDao" ref="userDao"/>
  900. </bean>
  901. <bean id="userDao" /><bean id="userService" >
  902.     <property name="userDao" ref="userDao"/>
  903. </bean>
  904. <bean id="userDao" />String idStr = request.getParameter("id");<bean id="userService" >
  905.     <property name="userDao" ref="userDao"/>
  906. </bean>
  907. <bean id="userDao" /><bean id="userService" >
  908.     <property name="userDao" ref="userDao"/>
  909. </bean>
  910. <bean id="userDao" /><bean id="userService" >
  911.     <property name="userDao" ref="userDao"/>
  912. </bean>
  913. <bean id="userDao" />if (idStr == null || idStr.isEmpty()) {<bean id="userService" >
  914.     <property name="userDao" ref="userDao"/>
  915. </bean>
  916. <bean id="userDao" /><bean id="userService" >
  917.     <property name="userDao" ref="userDao"/>
  918. </bean>
  919. <bean id="userDao" /><bean id="userService" >
  920.     <property name="userDao" ref="userDao"/>
  921. </bean>
  922. <bean id="userDao" /><bean id="userService" >
  923.     <property name="userDao" ref="userDao"/>
  924. </bean>
  925. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  926.     <property name="userDao" ref="userDao"/>
  927. </bean>
  928. <bean id="userDao" /><bean id="userService" >
  929.     <property name="userDao" ref="userDao"/>
  930. </bean>
  931. <bean id="userDao" /><bean id="userService" >
  932.     <property name="userDao" ref="userDao"/>
  933. </bean>
  934. <bean id="userDao" /><bean id="userService" >
  935.     <property name="userDao" ref="userDao"/>
  936. </bean>
  937. <bean id="userDao" /><bean id="userService" >
  938.     <property name="userDao" ref="userDao"/>
  939. </bean>
  940. <bean id="userDao" />ApiResponse.badRequest("用户ID不能为空").toMap()<bean id="userService" >
  941.     <property name="userDao" ref="userDao"/>
  942. </bean>
  943. <bean id="userDao" /><bean id="userService" >
  944.     <property name="userDao" ref="userDao"/>
  945. </bean>
  946. <bean id="userDao" /><bean id="userService" >
  947.     <property name="userDao" ref="userDao"/>
  948. </bean>
  949. <bean id="userDao" /><bean id="userService" >
  950.     <property name="userDao" ref="userDao"/>
  951. </bean>
  952. <bean id="userDao" />);<bean id="userService" >
  953.     <property name="userDao" ref="userDao"/>
  954. </bean>
  955. <bean id="userDao" /><bean id="userService" >
  956.     <property name="userDao" ref="userDao"/>
  957. </bean>
  958. <bean id="userDao" /><bean id="userService" >
  959.     <property name="userDao" ref="userDao"/>
  960. </bean>
  961. <bean id="userDao" />}<bean id="userService" >
  962.     <property name="userDao" ref="userDao"/>
  963. </bean>
  964. <bean id="userDao" /><bean id="userService" >
  965.     <property name="userDao" ref="userDao"/>
  966. </bean>
  967. <bean id="userDao" /><bean id="userService" >
  968.     <property name="userDao" ref="userDao"/>
  969. </bean>
  970. <bean id="userDao" />Long id = Long.parseLong(idStr);<bean id="userService" >
  971.     <property name="userDao" ref="userDao"/>
  972. </bean>
  973. <bean id="userDao" /><bean id="userService" >
  974.     <property name="userDao" ref="userDao"/>
  975. </bean>
  976. <bean id="userDao" /><bean id="userService" >
  977.     <property name="userDao" ref="userDao"/>
  978. </bean>
  979. <bean id="userDao" />boolean success = userService.deleteUser(id);<bean id="userService" >
  980.     <property name="userDao" ref="userDao"/>
  981. </bean>
  982. <bean id="userDao" /><bean id="userService" >
  983.     <property name="userDao" ref="userDao"/>
  984. </bean>
  985. <bean id="userDao" /><bean id="userService" >
  986.     <property name="userDao" ref="userDao"/>
  987. </bean>
  988. <bean id="userDao" />if (success) {<bean id="userService" >
  989.     <property name="userDao" ref="userDao"/>
  990. </bean>
  991. <bean id="userDao" /><bean id="userService" >
  992.     <property name="userDao" ref="userDao"/>
  993. </bean>
  994. <bean id="userDao" /><bean id="userService" >
  995.     <property name="userDao" ref="userDao"/>
  996. </bean>
  997. <bean id="userDao" /><bean id="userService" >
  998.     <property name="userDao" ref="userDao"/>
  999. </bean>
  1000. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  1001.     <property name="userDao" ref="userDao"/>
  1002. </bean>
  1003. <bean id="userDao" /><bean id="userService" >
  1004.     <property name="userDao" ref="userDao"/>
  1005. </bean>
  1006. <bean id="userDao" /><bean id="userService" >
  1007.     <property name="userDao" ref="userDao"/>
  1008. </bean>
  1009. <bean id="userDao" /><bean id="userService" >
  1010.     <property name="userDao" ref="userDao"/>
  1011. </bean>
  1012. <bean id="userDao" /><bean id="userService" >
  1013.     <property name="userDao" ref="userDao"/>
  1014. </bean>
  1015. <bean id="userDao" />ApiResponse.success(null, "删除用户成功").toMap()<bean id="userService" >
  1016.     <property name="userDao" ref="userDao"/>
  1017. </bean>
  1018. <bean id="userDao" /><bean id="userService" >
  1019.     <property name="userDao" ref="userDao"/>
  1020. </bean>
  1021. <bean id="userDao" /><bean id="userService" >
  1022.     <property name="userDao" ref="userDao"/>
  1023. </bean>
  1024. <bean id="userDao" /><bean id="userService" >
  1025.     <property name="userDao" ref="userDao"/>
  1026. </bean>
  1027. <bean id="userDao" />);<bean id="userService" >
  1028.     <property name="userDao" ref="userDao"/>
  1029. </bean>
  1030. <bean id="userDao" /><bean id="userService" >
  1031.     <property name="userDao" ref="userDao"/>
  1032. </bean>
  1033. <bean id="userDao" /><bean id="userService" >
  1034.     <property name="userDao" ref="userDao"/>
  1035. </bean>
  1036. <bean id="userDao" />} else {<bean id="userService" >
  1037.     <property name="userDao" ref="userDao"/>
  1038. </bean>
  1039. <bean id="userDao" /><bean id="userService" >
  1040.     <property name="userDao" ref="userDao"/>
  1041. </bean>
  1042. <bean id="userDao" /><bean id="userService" >
  1043.     <property name="userDao" ref="userDao"/>
  1044. </bean>
  1045. <bean id="userDao" /><bean id="userService" >
  1046.     <property name="userDao" ref="userDao"/>
  1047. </bean>
  1048. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  1049.     <property name="userDao" ref="userDao"/>
  1050. </bean>
  1051. <bean id="userDao" /><bean id="userService" >
  1052.     <property name="userDao" ref="userDao"/>
  1053. </bean>
  1054. <bean id="userDao" /><bean id="userService" >
  1055.     <property name="userDao" ref="userDao"/>
  1056. </bean>
  1057. <bean id="userDao" /><bean id="userService" >
  1058.     <property name="userDao" ref="userDao"/>
  1059. </bean>
  1060. <bean id="userDao" /><bean id="userService" >
  1061.     <property name="userDao" ref="userDao"/>
  1062. </bean>
  1063. <bean id="userDao" />ApiResponse.failure("删除用户失败").toMap()<bean id="userService" >
  1064.     <property name="userDao" ref="userDao"/>
  1065. </bean>
  1066. <bean id="userDao" /><bean id="userService" >
  1067.     <property name="userDao" ref="userDao"/>
  1068. </bean>
  1069. <bean id="userDao" /><bean id="userService" >
  1070.     <property name="userDao" ref="userDao"/>
  1071. </bean>
  1072. <bean id="userDao" /><bean id="userService" >
  1073.     <property name="userDao" ref="userDao"/>
  1074. </bean>
  1075. <bean id="userDao" />);<bean id="userService" >
  1076.     <property name="userDao" ref="userDao"/>
  1077. </bean>
  1078. <bean id="userDao" /><bean id="userService" >
  1079.     <property name="userDao" ref="userDao"/>
  1080. </bean>
  1081. <bean id="userDao" /><bean id="userService" >
  1082.     <property name="userDao" ref="userDao"/>
  1083. </bean>
  1084. <bean id="userDao" />}<bean id="userService" >
  1085.     <property name="userDao" ref="userDao"/>
  1086. </bean>
  1087. <bean id="userDao" /><bean id="userService" >
  1088.     <property name="userDao" ref="userDao"/>
  1089. </bean>
  1090. <bean id="userDao" />} catch (Exception e) {<bean id="userService" >
  1091.     <property name="userDao" ref="userDao"/>
  1092. </bean>
  1093. <bean id="userDao" /><bean id="userService" >
  1094.     <property name="userDao" ref="userDao"/>
  1095. </bean>
  1096. <bean id="userDao" /><bean id="userService" >
  1097.     <property name="userDao" ref="userDao"/>
  1098. </bean>
  1099. <bean id="userDao" />return new JsonResult(<bean id="userService" >
  1100.     <property name="userDao" ref="userDao"/>
  1101. </bean>
  1102. <bean id="userDao" /><bean id="userService" >
  1103.     <property name="userDao" ref="userDao"/>
  1104. </bean>
  1105. <bean id="userDao" /><bean id="userService" >
  1106.     <property name="userDao" ref="userDao"/>
  1107. </bean>
  1108. <bean id="userDao" /><bean id="userService" >
  1109.     <property name="userDao" ref="userDao"/>
  1110. </bean>
  1111. <bean id="userDao" />ApiResponse.failure("删除用户失败: " + e.getMessage()).toMap()<bean id="userService" >
  1112.     <property name="userDao" ref="userDao"/>
  1113. </bean>
  1114. <bean id="userDao" /><bean id="userService" >
  1115.     <property name="userDao" ref="userDao"/>
  1116. </bean>
  1117. <bean id="userDao" /><bean id="userService" >
  1118.     <property name="userDao" ref="userDao"/>
  1119. </bean>
  1120. <bean id="userDao" />);<bean id="userService" >
  1121.     <property name="userDao" ref="userDao"/>
  1122. </bean>
  1123. <bean id="userDao" /><bean id="userService" >
  1124.     <property name="userDao" ref="userDao"/>
  1125. </bean>
  1126. <bean id="userDao" />}<bean id="userService" >
  1127.     <property name="userDao" ref="userDao"/>
  1128. </bean>
  1129. <bean id="userDao" />}}
复制代码
5. 统一响应封装 - ApiResponse

为了简化Controller代码,我们提供了ApiResponse工具类:
  1. public class ApiResponse {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />private Integer code;<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private String message;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />private Object data;<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />// 成功响应<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />public static ApiResponse success(Object data, String message) {<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" /><bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />return new ApiResponse(200, message, data);<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />}<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />// 分页响应<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />public static ApiResponse page(List list, int page, int pageSize, long total) {<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />PageResult pageResult = PageResult.of(list, page, pageSize, total);<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />return success(pageResult, "获取列表成功");<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />}<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />// 失败响应<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />public static ApiResponse failure(String message) {<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />return new ApiResponse(500, message, null);<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" />}<bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />public static ApiResponse badRequest(String message) {<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" /><bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" />return new ApiResponse(400, message, null);<bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" />}<bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />public static ApiResponse notFound(String message) {<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" />return new ApiResponse(404, message, null);<bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" />}}
复制代码
对比一下:
传统方式(手动构建Map):
  1. public class User {
  2.     private Long id;
  3.     private String name;
  4.     private String email;
  5.     private String phone;
  6.     private Long createdTime;
  7.     private Long updatedTime;
  8.     // getter/setter省略
  9. }
复制代码
使用ApiResponse(一行搞定):
  1. @Repository
  2. public class UserDao {
  3.     @Autowired
  4.     private JdbcTemplate jdbcTemplate;
  5.     // 查询所有用户
  6.     public List<User> findAll() {
  7.         return jdbcTemplate.query(
  8.             "SELECT * FROM users ORDER BY id DESC",
  9.             this::mapRow
  10.         );
  11.     }
  12.     // 根据ID查询
  13.     public User findById(Long id) {
  14.         return jdbcTemplate.queryForObject(
  15.             "SELECT * FROM users WHERE id = ?",
  16.             this::mapRow,
  17.             id
  18.         );
  19.     }
  20.     // 分页查询
  21.     public List<User> findByPage(int page, int pageSize) {
  22.         int offset = (page - 1) * pageSize;
  23.         return jdbcTemplate.query(
  24.             "SELECT * FROM users ORDER BY id DESC LIMIT ? OFFSET ?",
  25.             this::mapRow,
  26.             pageSize, offset
  27.         );
  28.     }
  29.     // 创建用户
  30.     public int insert(User user) {
  31.         return jdbcTemplate.update(
  32.             "INSERT INTO users (name, email, phone, created_time, updated_time) " +
  33.             "VALUES (?, ?, ?, ?, ?)",
  34.             user.getName(), user.getEmail(), user.getPhone(),
  35.             System.currentTimeMillis(), System.currentTimeMillis()
  36.         );
  37.     }
  38.     // 更新用户
  39.     public int update(User user) {
  40.         return jdbcTemplate.update(
  41.             "UPDATE users SET name = ?, email = ?, phone = ?, " +
  42.             "updated_time = ? WHERE id = ?",
  43.             user.getName(), user.getEmail(), user.getPhone(),
  44.             System.currentTimeMillis(), user.getId()
  45.         );
  46.     }
  47.     // 删除用户
  48.     public int delete(Long id) {
  49.         return jdbcTemplate.update("DELETE FROM users WHERE id = ?", id);
  50.     }
  51.     // 结果集映射
  52.     private User mapRow(ResultSet rs, int rowNum) throws SQLException {
  53.         User user = new User();
  54.         user.setId(rs.getLong("id"));
  55.         user.setName(rs.getString("name"));
  56.         user.setEmail(rs.getString("email"));
  57.         user.setPhone(rs.getString("phone"));
  58.         user.setCreatedTime(rs.getLong("created_time"));
  59.         user.setUpdatedTime(rs.getLong("updated_time"));
  60.         return user;
  61.     }
  62. }
复制代码
6. 分页结果 - PageResult

分页是Web应用的常见需求,SpringWind提供了PageResult:
  1. public class PageResult {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />private List list;<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />  // 数据列表<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />private Integer page;<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />  // 当前页码<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />private Integer pageSize;<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />  // 每页大小<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />private Long total;<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />// 总记录数<bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />private Integer totalPages;<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />// 总页数<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" />private Boolean hasPrevious;   // 是否有上一页<bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />private Boolean hasNext;<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />   // 是否有下一页<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" />private Boolean first;<bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" /><bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /> // 是否是第一页<bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />private Boolean last;<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" /><bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" />  // 是否是最后一页<bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" />// 创建分页结果<bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />public static  PageResult of(List list, int page, int pageSize, long total) {<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" />PageResult result = new PageResult();<bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" /><bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" />result.setList(list);<bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" /><bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" />result.setPage(page);<bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" /><bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" />result.setPageSize(pageSize);<bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" /><bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" />result.setTotal(total);<bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" /><bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" />result.setTotalPages((int) Math.ceil((double) total / pageSize));<bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" /><bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" />result.setHasPrevious(page > 1);<bean id="userService" >
  119.     <property name="userDao" ref="userDao"/>
  120. </bean>
  121. <bean id="userDao" /><bean id="userService" >
  122.     <property name="userDao" ref="userDao"/>
  123. </bean>
  124. <bean id="userDao" />result.setHasNext(page < result.getTotalPages());<bean id="userService" >
  125.     <property name="userDao" ref="userDao"/>
  126. </bean>
  127. <bean id="userDao" /><bean id="userService" >
  128.     <property name="userDao" ref="userDao"/>
  129. </bean>
  130. <bean id="userDao" />result.setFirst(page == 1);<bean id="userService" >
  131.     <property name="userDao" ref="userDao"/>
  132. </bean>
  133. <bean id="userDao" /><bean id="userService" >
  134.     <property name="userDao" ref="userDao"/>
  135. </bean>
  136. <bean id="userDao" />result.setLast(page == result.getTotalPages());<bean id="userService" >
  137.     <property name="userDao" ref="userDao"/>
  138. </bean>
  139. <bean id="userDao" /><bean id="userService" >
  140.     <property name="userDao" ref="userDao"/>
  141. </bean>
  142. <bean id="userDao" />return result;<bean id="userService" >
  143.     <property name="userDao" ref="userDao"/>
  144. </bean>
  145. <bean id="userDao" />}}
复制代码
分页响应示例:
  1. {  "code": 200,  "message": "获取列表成功",  "data": {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />"list": [<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />  {"id": 1, "name": "admin", "email": "admin@example.com"},<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />  {"id": 2, "name": "test", "email": "test@example.com"}<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />],<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />"page": 2,<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />"pageSize": 10,<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />"total": 100,<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />"totalPages": 10,<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />"hasPrevious": true,<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />"hasNext": true,<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />"first": false,<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" />"last": false  }}
复制代码
前端可以根据hasPrevious和hasNext来禁用/启用分页按钮,非常方便。
7. 启动应用
  1. public class UserDemoApplication {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />public static void main(String[] args) {<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" /><bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />if (args.length > 0 && "--web".equals(args[0])) {<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />// Web模式:启动嵌入式Tomcat<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />startWebServer();<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />} else {<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" />// 控制台模式:直接运行<bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" /><bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" />runConsoleDemo();<bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />}<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" />}<bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" />private static void startWebServer() {<bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" /><bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" />// 创建SpringWind容器<bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />SpringWindApplicationContext context =<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" /><bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" />new SpringWindApplicationContext(UserDemoApplication.class);<bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" /><bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" />// 启动Tomcat<bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" /><bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" />Tomcat tomcat = new Tomcat();<bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" /><bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" />tomcat.setPort(8080);<bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" /><bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" />// ... 配置Servlet<bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" /><bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" />tomcat.start();<bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" />}}
复制代码
8. API测试
  1. Map<String, Object> result = new HashMap<>();
  2. result.put("code", 200);
  3. result.put("message", "获取用户成功");
  4. result.put("data", user);
  5. return new JsonResult(result);
复制代码
示例2:Web Demo - 企业网站内容管理系统

这是一个企业网站的CMS系统,展示了SpringWind的Web MVC功能。请见examples/web-demo,此处不再展开。
Springwind改进点

SpringWind目前实现了Spring的核心功能,但还有很多可以改进的地方。
已实现的功能 ✅


  • IoC容器(组件扫描、Bean管理)
  • 依赖注入(字段注入、方法注入)
  • 循环依赖解决(三级缓存)
  • AOP(JDK动态代理、CGLIB代理)
  • Web MVC(请求映射、参数绑定、JSON响应)
  • JDBC模板(查询、更新、批量操作)
  • 分页支持(PageResult)
  • 统一响应封装(ApiResponse)
待改进的功能 ⏳

1. 事务管理

当前状态: 没有事务支持,需要手动管理
改进方案:
  1. // 声明式事务@Servicepublic class UserService {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@Transactional<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />public void registerUser(User user) {<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" /><bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />userDao.insert(user);<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />emailService.sendWelcomeEmail(user);  // 如果发邮件失败,用户创建也回滚<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />}}// 实现思路:利用AOP拦截@Transactional方法@Aspectpublic class TransactionAspect {<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />@Around("@annotation(Transactional)")<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />public Object aroundTransaction(Method method, Object[] args) {<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" /><bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" />Connection conn = null;<bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" />try {<bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />conn = dataSource.getConnection();<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" /><bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" /><bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />conn.setAutoCommit(false);  // 开启事务<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" /><bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" /><bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />Object result = method.invoke(args);  // 执行业务方法<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" /><bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" />conn.commit();  // 提交事务<bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" /><bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" /><bean id="userService" >
  83.     <property name="userDao" ref="userDao"/>
  84. </bean>
  85. <bean id="userDao" />return result;<bean id="userService" >
  86.     <property name="userDao" ref="userDao"/>
  87. </bean>
  88. <bean id="userDao" /><bean id="userService" >
  89.     <property name="userDao" ref="userDao"/>
  90. </bean>
  91. <bean id="userDao" />} catch (Exception e) {<bean id="userService" >
  92.     <property name="userDao" ref="userDao"/>
  93. </bean>
  94. <bean id="userDao" /><bean id="userService" >
  95.     <property name="userDao" ref="userDao"/>
  96. </bean>
  97. <bean id="userDao" /><bean id="userService" >
  98.     <property name="userDao" ref="userDao"/>
  99. </bean>
  100. <bean id="userDao" />if (conn != null) {<bean id="userService" >
  101.     <property name="userDao" ref="userDao"/>
  102. </bean>
  103. <bean id="userDao" /><bean id="userService" >
  104.     <property name="userDao" ref="userDao"/>
  105. </bean>
  106. <bean id="userDao" /><bean id="userService" >
  107.     <property name="userDao" ref="userDao"/>
  108. </bean>
  109. <bean id="userDao" /><bean id="userService" >
  110.     <property name="userDao" ref="userDao"/>
  111. </bean>
  112. <bean id="userDao" />conn.rollback();  // 回滚事务<bean id="userService" >
  113.     <property name="userDao" ref="userDao"/>
  114. </bean>
  115. <bean id="userDao" /><bean id="userService" >
  116.     <property name="userDao" ref="userDao"/>
  117. </bean>
  118. <bean id="userDao" /><bean id="userService" >
  119.     <property name="userDao" ref="userDao"/>
  120. </bean>
  121. <bean id="userDao" />}<bean id="userService" >
  122.     <property name="userDao" ref="userDao"/>
  123. </bean>
  124. <bean id="userDao" /><bean id="userService" >
  125.     <property name="userDao" ref="userDao"/>
  126. </bean>
  127. <bean id="userDao" /><bean id="userService" >
  128.     <property name="userDao" ref="userDao"/>
  129. </bean>
  130. <bean id="userDao" />throw e;<bean id="userService" >
  131.     <property name="userDao" ref="userDao"/>
  132. </bean>
  133. <bean id="userDao" /><bean id="userService" >
  134.     <property name="userDao" ref="userDao"/>
  135. </bean>
  136. <bean id="userDao" />}<bean id="userService" >
  137.     <property name="userDao" ref="userDao"/>
  138. </bean>
  139. <bean id="userDao" />}}
复制代码
2. 构造器注入

当前状态: 只支持字段注入和方法注入
改进方案:
  1. // 支持构造器注入@Servicepublic class UserService {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />private final UserDao userDao;  // final保证不可变<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />@Autowired<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />public UserService(UserDao userDao) {<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" /><bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />this.userDao = userDao;<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />}}// 实现思路:// 1. 扫描构造器上的@Autowired// 2. 解析构造器参数类型// 3. 从容器中查找对应的Bean// 4. 调用构造器创建对象
复制代码
3. Bean作用域

当前状态: 只支持单例(Singleton)
改进方案:
  1. @Service@Scope("prototype")  // 每次获取都创建新实例public class PrototypeService {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// ...}@Service@Scope("request")  // 每个HTTP请求一个实例public class RequestScopedService {<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />// ...}
复制代码
4. 更强大的AOP

当前改进:

  • 支持切点表达式
  1. @Before("execution(* com.example.service.*.*(..))") // 支持AspectJ表达式public void logBefore(JoinPoint joinPoint) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// ...}
复制代码

  • 支持切点组合
  1. @Pointcut("execution(* com.example.service.*.*(..))")public void serviceMethods() {}@Pointcut("@annotation(Transactional)")public void transactionalMethods() {}@Before("serviceMethods() && transactionalMethods()")public void beforeServiceTransaction() {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />// 同时满足两个切点}
复制代码

  • 支持@Around获取方法参数
  1. @Around("com.example.service.*.*")public Object aroundAdvice(ProceedingJoinPoint pjp) {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />Object[] args = pjp.getArgs();  // 获取方法参数<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />System.out.println("参数: " + Arrays.toString(args));<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />return pjp.proceed();  // 继续执行}
复制代码
5. 更轻量级化

当前体积: 核心代码约2000行,依赖较少
进一步优化:

  • 按需加载模块
  1. <bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />com.github.microwind<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />springwind-core<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />  com.github.microwind<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />springwind-web  
复制代码

  • 移除不必要的依赖
  1. <bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />cglib<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />cglib<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />true  
复制代码

  • GraalVM Native Image支持
    编译成原生可执行文件,启动速度更快,内存占用更小。
6. 配置文件支持

当前状态: 主要依赖注解
改进方案:
  1. # application.ymlspringwind:  datasource:<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />url: jdbc:mysql://localhost:3306/test<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />username: root<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />password: 123456  web:<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />port: 8080<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />context-path: /api
复制代码
  1. // 读取配置@Configurationpublic class DataSourceConfig {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@Value("${springwind.datasource.url}")<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />private String url;<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" />@Bean<bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />public DataSource dataSource() {<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />return new HikariDataSource(url, username, password);<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />}}
复制代码
7. 更好的异常处理

当前状态: 基本的异常抛出
改进方案:
  1. // 全局异常处理器@ControllerAdvicepublic class GlobalExceptionHandler {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@ExceptionHandler(BeanNotFoundException.class)<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />public ViewResult handleBeanNotFound(BeanNotFoundException e) {<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" /><bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />return new JsonResult(ApiResponse.notFound(e.getMessage()).toMap());<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" />}<bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />@ExceptionHandler(Exception.class)<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" />public ViewResult handleGenericException(Exception e) {<bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" /><bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" />return new JsonResult(ApiResponse.failure("系统错误: " + e.getMessage()).toMap());<bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />}}
复制代码
8. 性能监控和诊断

改进方案:
  1. // Bean创建性能监控@Aspectpublic class BeanCreationMonitor {<bean id="userService" >
  2.     <property name="userDao" ref="userDao"/>
  3. </bean>
  4. <bean id="userDao" />@Around("@annotation(Component)")<bean id="userService" >
  5.     <property name="userDao" ref="userDao"/>
  6. </bean>
  7. <bean id="userDao" />public Object monitorBeanCreation(ProceedingJoinPoint pjp) {<bean id="userService" >
  8.     <property name="userDao" ref="userDao"/>
  9. </bean>
  10. <bean id="userDao" /><bean id="userService" >
  11.     <property name="userDao" ref="userDao"/>
  12. </bean>
  13. <bean id="userDao" />long start = System.currentTimeMillis();<bean id="userService" >
  14.     <property name="userDao" ref="userDao"/>
  15. </bean>
  16. <bean id="userDao" /><bean id="userService" >
  17.     <property name="userDao" ref="userDao"/>
  18. </bean>
  19. <bean id="userDao" />Object bean = pjp.proceed();<bean id="userService" >
  20.     <property name="userDao" ref="userDao"/>
  21. </bean>
  22. <bean id="userDao" /><bean id="userService" >
  23.     <property name="userDao" ref="userDao"/>
  24. </bean>
  25. <bean id="userDao" />long end = System.currentTimeMillis();<bean id="userService" >
  26.     <property name="userDao" ref="userDao"/>
  27. </bean>
  28. <bean id="userDao" /><bean id="userService" >
  29.     <property name="userDao" ref="userDao"/>
  30. </bean>
  31. <bean id="userDao" />System.out.println("创建Bean " + bean.getClass().getSimpleName() +<bean id="userService" >
  32.     <property name="userDao" ref="userDao"/>
  33. </bean>
  34. <bean id="userDao" /><bean id="userService" >
  35.     <property name="userDao" ref="userDao"/>
  36. </bean>
  37. <bean id="userDao" /><bean id="userService" >
  38.     <property name="userDao" ref="userDao"/>
  39. </bean>
  40. <bean id="userDao" /><bean id="userService" >
  41.     <property name="userDao" ref="userDao"/>
  42. </bean>
  43. <bean id="userDao" /><bean id="userService" >
  44.     <property name="userDao" ref="userDao"/>
  45. </bean>
  46. <bean id="userDao" /><bean id="userService" >
  47.     <property name="userDao" ref="userDao"/>
  48. </bean>
  49. <bean id="userDao" />  " 耗时: " + (end - start) + "ms");<bean id="userService" >
  50.     <property name="userDao" ref="userDao"/>
  51. </bean>
  52. <bean id="userDao" /><bean id="userService" >
  53.     <property name="userDao" ref="userDao"/>
  54. </bean>
  55. <bean id="userDao" />return bean;<bean id="userService" >
  56.     <property name="userDao" ref="userDao"/>
  57. </bean>
  58. <bean id="userDao" />}}// 内存占用监控public class MemoryMonitor {<bean id="userService" >
  59.     <property name="userDao" ref="userDao"/>
  60. </bean>
  61. <bean id="userDao" />public void printMemoryUsage() {<bean id="userService" >
  62.     <property name="userDao" ref="userDao"/>
  63. </bean>
  64. <bean id="userDao" /><bean id="userService" >
  65.     <property name="userDao" ref="userDao"/>
  66. </bean>
  67. <bean id="userDao" />Runtime runtime = Runtime.getRuntime();<bean id="userService" >
  68.     <property name="userDao" ref="userDao"/>
  69. </bean>
  70. <bean id="userDao" /><bean id="userService" >
  71.     <property name="userDao" ref="userDao"/>
  72. </bean>
  73. <bean id="userDao" />long usedMemory = runtime.totalMemory() - runtime.freeMemory();<bean id="userService" >
  74.     <property name="userDao" ref="userDao"/>
  75. </bean>
  76. <bean id="userDao" /><bean id="userService" >
  77.     <property name="userDao" ref="userDao"/>
  78. </bean>
  79. <bean id="userDao" />System.out.println("内存占用: " + (usedMemory / 1024 / 1024) + " MB");<bean id="userService" >
  80.     <property name="userDao" ref="userDao"/>
  81. </bean>
  82. <bean id="userDao" />}}
复制代码
总结

通过从零实现SpringWind框架(~5000行代码),我们彻底搞懂了Spring的核心原理:
核心机制理解


  • IoC容器:通过反射扫描组件、注册Bean定义、管理完整生命周期

    • 组件扫描:支持文件系统和JAR包中的类扫描
    • Bean注册:使用ConcurrentHashMap保证线程安全
    • 生命周期:从实例化到初始化到销毁的完整流程

  • 依赖注入:通过反射实现自动装配,支持字段注入和方法注入

    • 类型匹配:根据字段类型自动查找Bean
    • 循环依赖:与三级缓存配合,优雅解决循环依赖问题

  • 三级缓存(最精妙的设计):

    • 一级缓存:存储完全初始化好的Bean
    • 二级缓存:存储早期Bean引用(已实例化但未初始化)
    • 三级缓存:存储ObjectFactory工厂(关键!
    • 为什么需要三级:延迟生成早期引用,支持AOP提前创建代理,保证单例一致性

  • AOP:通过动态代理实现横切关注点的分离

    • JDK动态代理:基于接口的代理
    • CGLIB代理:基于继承的字节码增强
    • SmartInstantiationAwareBeanPostProcessor:解决循环依赖+AOP的组合问题

  • Web MVC:通过前端控制器模式统一处理HTTP请求

    • DispatcherServlet:统一入口
    • HandlerMapping:URL到方法的映射
    • 参数解析:支持@PathVariable、@RequestParam、@RequestBody

  • JDBC模板:通过模板方法模式封装样板代码

    • 固定流程:连接管理、语句执行、结果映射、资源关闭
    • 灵活扩展:通过RowMapper实现不同的映射策略

学习价值

为了就是模仿,只有通过模仿完全手搓一个Web框架时,你才能彻底明白框架的核心机制。
SpringWind不是为了替代Spring,而是为了深入理解Spring。它用最简洁的代码(~3800行)实现了Spring的核心功能,让每个想深入理解框架原理的开发者都能看懂。
通过学习SpringWind,你将掌握Spring框架核心知识点:

  • ✅ Spring IoC容器的工作机制
  • ✅ 三级缓存解决循环依赖的精妙设计
  • ✅ AOP动态代理的实现原理
  • ✅ Bean生命周期的完整流程
  • ✅ 设计模式在框架中的实际应用
  • ✅ 为什么Spring要这样设计的深层原因
学习建议:

  • 先跑起来:运行两个示例项目,看看效果
  • 打断点调试:看Bean是怎么创建的,依赖是怎么注入的
  • 阅读源码:SpringWind代码量不大,完全可以通读
  • 对比Spring:理解SpringWind的简化设计和Spring的完整实现
  • 动手改代码:实现待改进功能,加深理解
最后的话:
框架不是黑魔法,它只是把常见的代码模式封装起来。当你理解了原理,就能从"会用框架"进阶到"精通框架",甚至"设计框架"。

希望SpringWind能帮你打开Spring的大门,祝你学习愉快!
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

7 天前

举报

懂技术并乐意极积无私分享的人越来越少。珍惜
您需要登录后才可以回帖 登录 | 立即注册