极高 进阶
Spring中的设计模式#
一句话答案#
Spring 大量应用设计模式:工厂(BeanFactory)、单例(Bean 默认)、代理(AOP)、模板方法(JdbcTemplate)、观察者(事件)、责任链(Filter)。
核心要点
Spring 是设计模式的集大成者,几乎每个核心组件都能找到经典模式的影子:
| 设计模式 | Spring 中的体现 | 说明 |
|---|---|---|
| 工厂模式 | BeanFactory、ApplicationContext | IoC 容器本身就是一个大工厂,通过配置/注解创建并管理 Bean |
| 单例模式 | Bean 默认作用域 singleton | Spring Bean 默认单例,由容器保证唯一性(非传统私有构造函数方式) |
| 代理模式 | Spring AOP(JDK 动态代理 / CGLIB) | @Transactional、@Async、@Cacheable 等注解的底层实现 → 详见 Spring-AOP原理 |
| 模板方法模式 | JdbcTemplate、RedisTemplate、RestTemplate | 定义操作骨架(获取连接→执行→释放资源),用户通过回调传入具体 SQL/操作逻辑(模板+回调变体);RestTemplate 在 Spring 6.1 起推荐改用 RestClient,计划 7.1 标记废弃 |
| 观察者模式 | ApplicationEvent + ApplicationListener / @EventListener | Spring 事件机制,发布-订阅模型 |
| 策略模式 | Resource 接口(ClassPathResource/UrlResource等) | 根据不同前缀自动选择资源加载策略 |
| 适配器模式 | HandlerAdapter(Spring MVC) | 不同类型的 Controller(注解式、实现接口式)通过适配器统一调用 |
| 装饰器模式 | TransactionAwareCacheDecorator、ContentCachingRequestWrapper | 包装原对象并增强:前者让缓存写入等到事务提交后执行,后者(继承 Servlet 的 HttpServletRequestWrapper)缓存请求体以便重复读取 |
| 责任链模式 | Spring Security 过滤器链 | 多个 Filter 按顺序处理请求,每个 Filter 决定是否放行 |
| 建造者模式 | BeanDefinitionBuilder、UriComponentsBuilder | 链式构建复杂对象 |
面试时重点讲 3-4 个: 工厂(BeanFactory)、代理(AOP)、模板方法(JdbcTemplate)、观察者(Event),每个都能展开一两句说清楚。
面试回答(2分钟版)
Spring框架是设计模式的集大成者,我重点讲几个核心的。第一是工厂模式,BeanFactory和ApplicationContext本身就是大工厂,根据配置或注解创建管理Bean实例。第二是单例模式,Spring Bean默认作用域是singleton,但它不是传统的私有构造函数实现,而是容器级别的单例,由IoC容器保证同一个BeanName只有一个实例。第三是代理模式,这是Spring AOP的核心,@Transactional、@Async、@Cacheable这些注解底层都是通过JDK动态代理或CGLIB生成代理对象来实现的。第四是模板方法模式,JdbcTemplate、RedisTemplate定义了操作骨架——获取连接、执行操作、释放资源,我们只需要传入具体的SQL或操作逻辑。第五是观察者模式,ApplicationEvent加ApplicationListener实现了发布订阅机制,比如监听容器启动事件做初始化。此外还有策略模式体现在Resource接口的多种实现、适配器模式体现在HandlerAdapter、责任链模式体现在Spring Security的过滤器链。
追问与易错
追问方向:
- “策略模式体现在哪?”→ Resource 接口根据不同前缀(classpath:/file:/http:)自动选择 ClassPathResource/FileSystemResource/UrlResource 实现,HandlerMapping 按策略选择不同的 Handler
- “为什么说 Spring 是设计模式典范?”→ 几乎每个核心组件都有经典模式的影子:工厂(BeanFactory)、单例(Bean 默认)、代理(AOP)、模板方法(JdbcTemplate)、观察者(Event)、责任链(Filter)等至少 10 种
- “DispatcherServlet 用了哪些模式?”→ 前端控制器模式(统一入口接收所有请求)、策略模式(HandlerMapping 选择处理器)、适配器模式(HandlerAdapter 适配不同类型 Handler)
易错点:
- ❌ Spring 单例就是 GoF 单例——Spring 是”每个容器内每个 bean 名一个实例”,同一个类可以注册成多个 bean,也不需要私有构造器
- ❌ BeanFactory 和 FactoryBean 是一回事——BeanFactory 是 IoC 容器本身;FactoryBean 是容器里一个”生产复杂 Bean 的工厂 Bean”,
getBean("name")拿到的是它getObject()的返回值,&name才拿到它自己 - ❌ Spring AOP 默认用 JDK 动态代理——Spring Framework 本身是有接口用 JDK 代理,但 Spring Boot 2.0 起默认
spring.aop.proxy-target-class=true,统一用 CGLIB