📌 PDF :大白话说Java面试题 --- 06_Spring篇
第16题:Spring 用到了哪些设计模式?
📚 回答:
- 核心考点 : Spring 框架是设计模式的集大成者,大厂面试不会只问"用了哪些模式",而是深入考察 每种模式在 Spring 中的具体落地位置 (如
BeanFactory是哪种工厂模式变体)、模式之间的组合关系 (如 AOP 如何组合代理+装饰器+责任链)、以及从源码层面识别设计模式的实现细节 (如AbstractApplicationContext.refresh()的模板方法骨架、TransactionSynchronizationManager的线程级单例实现)。面试官真正想判断的是:你是否建立了"设计模式 → Spring 源码 → 工程实践"的完整认知链路,能否在扩展 Spring 时正确运用这些模式。
1. 单例模式(Singleton Pattern)
-
1.1 模式定义
确保一个类只有一个实例,并提供一个全局访问点。
-
1.2 Spring 中的应用
Spring 容器管理的 Bean 默认就是单例(
singleton),但 Spring 的单例实现并非传统的饿汉式/懒汉式,而是通过 IoC 容器统一管理:实现方式 说明 Spring 对应 饿汉式 类加载时创建 ❌ 不灵活 懒汉式 + 双重检查锁 首次使用时创建 ❌ 容器已管理 IoC 容器管理 容器控制生命周期 ✅ DefaultSingletonBeanRegistryjava// Spring 的单例实现:通过 ConcurrentHashMap 保证线程安全 public class DefaultSingletonBeanRegistry { private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); public Object getSingleton(String beanName) { return singletonObjects.get(beanName); // 全局唯一访问点 } }特殊单例 :
TransactionSynchronizationManager使用 ThreadLocal 实现线程级单例:javapublic abstract class TransactionSynchronizationManager { private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources"); // 每个线程有独立的事务资源,线程内单例 } -
1.3 单例模式在 Spring 中的变体
变体 实现类 说明 容器级单例 DefaultSingletonBeanRegistry整个容器共享 线程级单例 TransactionSynchronizationManagerThreadLocal 实现 请求级单例 RequestContextHolder当前请求共享
2. 工厂模式(Factory Pattern)
Spring 中工厂模式有三种变体:简单工厂 、工厂方法 、抽象工厂。
-
2.1 简单工厂(Simple Factory)
BeanFactory是最典型的简单工厂,根据 Bean 名称创建对象:javapublic interface BeanFactory { Object getBean(String name); // 简单工厂方法 <T> T getBean(String name, Class<T> requiredType); } -
2.2 工厂方法(Factory Method)
@Configuration+@Bean是工厂方法的典型应用:java@Configuration public class AppConfig { @Bean // 工厂方法 public UserService userService() { return new UserService(userDao()); // 控制创建逻辑 } @Bean public UserDao userDao() { return new UserDaoImpl(); } } -
2.3 抽象工厂(Abstract Factory)
FactoryBean接口是抽象工厂的实现,用于创建复杂对象:javapublic interface FactoryBean<T> { T getObject() throws Exception; // 创建对象 Class<?> getObjectType(); // 返回对象类型 boolean isSingleton(); // 是否单例 } // 典型应用:MyBatis-Spring 的 SqlSessionFactoryBean public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory> { @Override public SqlSessionFactory getObject() throws Exception { // 复杂配置:解析 XML、设置数据源、配置插件等 return sqlSessionFactoryBuilder.build(configuration); } } -
2.4 Spring 中工厂模式的完整图谱
模式变体 Spring 实现 用途 简单工厂 BeanFactory/ApplicationContext根据名称获取 Bean 工厂方法 @Bean方法 /FactoryBean自定义 Bean 创建逻辑 抽象工厂 AbstractFactoryBean创建复杂对象的模板 静态工厂 StaticFactoryMethod(XML)调用静态方法创建 实例工厂 InstanceFactoryMethod(XML)调用实例方法创建
3. 代理模式(Proxy Pattern)
-
3.1 静态代理 vs 动态代理
类型 实现方式 优点 缺点 Spring 应用 静态代理 手动编写代理类 简单直观 每个目标类都需要一个代理类,代码冗余 ❌ 不使用 JDK 动态代理 Proxy.newProxyInstance()基于接口,标准 Java 只能代理接口方法 ✅ AOP(有接口时) CGLIB 代理 ASM 字节码生成子类 可代理类方法 不能代理 final 方法/类 ✅ AOP(无接口时) -
3.2 Spring AOP 的代理实现
java// JDK 动态代理:基于接口 UserService proxy = (UserService) Proxy.newProxyInstance( classLoader, new Class[]{UserService.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) { // 前置增强 Object result = method.invoke(target, args); // 后置增强 return result; } } ); // CGLIB 代理:基于继承 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(OrderService.class); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) { // 前置增强 Object result = proxy.invokeSuper(obj, args); // 后置增强 return result; } }); OrderService proxy = (OrderService) enhancer.create(); -
3.3 代理选择策略
DefaultAopProxyFactory根据条件选择代理方式:javapublic class DefaultAopProxyFactory implements AopProxyFactory { @Override public AopProxy createAopProxy(AdvisedSupport config) { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) throw new AopConfigException("..."); if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); // JDK 代理 } return new ObjenesisCglibAopProxy(config); // CGLIB 代理 } return new JdkDynamicAopProxy(config); } }
4. 装饰器模式(Decorator Pattern)
-
4.1 模式定义
动态地为对象添加额外功能,而不改变其原始结构。与代理模式的区别在于:代理模式控制访问,装饰器模式增强功能。
-
4.2 Spring 中的应用
场景 装饰器类 说明 事务装饰 TransactionInterceptor为方法添加事务管理功能 缓存装饰 CacheInterceptor为方法添加缓存功能 HTTP 请求装饰 HttpServletRequestWrapper包装请求对象,添加功能 输入流装饰 DecoratingInputStream为流添加缓冲、加密等功能 java// HttpServletRequestWrapper:装饰器模式 public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public CustomHttpServletRequestWrapper(HttpServletRequest request) { super(request); this.body = readBody(request); // 读取并缓存请求体 } @Override public ServletInputStream getInputStream() { return new CachedServletInputStream(body); // 返回可重复读取的流 } }代理模式 vs 装饰器模式在 Spring 中的区别:
维度 代理模式(AOP) 装饰器模式(Wrapper) 目的 控制访问、延迟加载 增强功能 透明性 对客户端透明 通常显式使用 Spring 例子 @Transactional代理HttpServletRequestWrapper是否改变接口 否 否
5. 观察者模式(Observer Pattern)
-
5.1 模式定义
定义对象间的一对多依赖,当一个对象状态改变时,所有依赖者自动收到通知。
-
5.2 Spring 事件机制
Spring 的事件机制是观察者模式的完整实现:
java// 事件(被观察者) public class OrderCreatedEvent extends ApplicationEvent { private final Order order; public OrderCreatedEvent(Object source, Order order) { super(source); this.order = order; } } // 监听器(观察者) @Component public class OrderCreatedListener implements ApplicationListener<OrderCreatedEvent> { @Override public void onApplicationEvent(OrderCreatedEvent event) { // 处理订单创建事件:发送短信、更新库存等 notificationService.sendSms(event.getOrder().getUserId()); } } // 发布事件 @Service public class OrderService { @Autowired private ApplicationEventPublisher publisher; public void createOrder(Order order) { orderDao.save(order); publisher.publishEvent(new OrderCreatedEvent(this, order)); } }Spring 事件机制的扩展:
特性 说明 实现 同步/异步 @Async+@EventListenerSimpleApplicationEventMulticaster泛型事件 基于泛型类型匹配 ResolvableType条件监听 SpEL 表达式过滤 @EventListener(condition = "...")事务绑定 事务提交后才触发 @TransactionalEventListenerjava// 事务事件监听:事务成功提交后才发送消息 @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void handleOrderCreated(OrderCreatedEvent event) { kafkaTemplate.send("order-topic", event.getOrder()); }
6. 模板方法模式(Template Method Pattern)
-
6.1 模式定义
定义算法骨架,将可变步骤延迟到子类实现。
-
6.2 Spring 中的模板方法
模板类 固定步骤 可变步骤(子类实现) AbstractApplicationContext.refresh()准备刷新、获取 BeanFactory、注册 BeanPostProcessor、初始化单例等 postProcessBeanFactory()、onRefresh()JdbcTemplate.execute()获取连接、创建 Statement、执行 SQL、处理异常、释放资源 StatementCallback.doInStatement()RestTemplate.execute()创建请求、执行 HTTP、处理响应、错误处理 RequestCallback、ResponseExtractorHibernateTemplate获取 Session、开启事务、执行操作、提交/回滚 HibernateCallback.doInHibernate()java// AbstractApplicationContext.refresh():经典的模板方法 public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); // 固定步骤 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 固定 prepareBeanFactory(beanFactory); // 固定 postProcessBeanFactory(beanFactory); // ← 子类可重写 invokeBeanFactoryPostProcessors(beanFactory); // 固定 registerBeanPostProcessors(beanFactory); // 固定 initMessageSource(); // 固定 initApplicationEventMulticaster(); // 固定 onRefresh(); // ← 子类可重写(如创建 Tomcat) registerListeners(); // 固定 finishBeanFactoryInitialization(beanFactory); // 固定 finishRefresh(); // 固定 } } -
6.3 JdbcTemplate 的模板方法实现
javapublic class JdbcTemplate extends JdbcAccessor implements JdbcOperations { public <T> T query(final String sql, final ResultSetExtractor<T> rse) { // 模板方法:固定步骤 Connection con = DataSourceUtils.getConnection(getDataSource()); Statement stmt = null; ResultSet rs = null; try { stmt = con.createStatement(); rs = stmt.executeQuery(sql); return rse.extractData(rs); // ← 可变步骤:由调用方实现 } catch (SQLException ex) { // 异常处理:固定 throw translateException("Query", sql, ex); } finally { // 资源释放:固定 JdbcUtils.closeResultSet(rs); JdbcUtils.closeStatement(stmt); DataSourceUtils.releaseConnection(con, getDataSource()); } } }
7. 策略模式(Strategy Pattern)
-
7.1 模式定义
定义一系列算法,将它们封装起来,并且使它们可以互相替换。
-
7.2 Spring 中的应用
策略接口 具体策略 说明 ResourceClassPathResource、FileSystemResource、UrlResource不同来源的资源加载策略 InstantiationStrategySimpleInstantiationStrategy、CglibSubclassingInstantiationStrategy实例化策略 AopProxyJdkDynamicAopProxy、CglibAopProxyAOP 代理策略 TransactionManagerDataSourceTransactionManager、JtaTransactionManager事务管理策略 HandlerMappingRequestMappingHandlerMapping、BeanNameUrlHandlerMappingURL 映射策略 HandlerAdapterRequestMappingHandlerAdapter、HttpRequestHandlerAdapter处理器适配策略 java// Resource 策略:统一接口,不同实现 Resource classpathResource = new ClassPathResource("application.properties"); Resource fileResource = new FileSystemResource("/tmp/config.properties"); Resource urlResource = new UrlResource("https://example.com/config.properties"); // 统一使用:resource.getInputStream()
8. 责任链模式(Chain of Responsibility Pattern)
-
8.1 模式定义
将请求沿着处理链传递,每个处理器决定是否处理或传递给下一个。
-
8.2 Spring 中的应用
场景 责任链实现 说明 AOP 拦截器链 ReflectiveMethodInvocation多个通知(Advice)形成调用链 Spring Security 过滤器链 FilterChainProxySecurityFilterChain中的多个FilterHandlerInterceptor HandlerExecutionChain拦截器链:preHandle → 目标方法 → postHandle → afterCompletion java// AOP 拦截器链:责任链模式 public class ReflectiveMethodInvocation implements ProxyMethodInvocation { private int currentInterceptorIndex = -1; private List<Object> interceptorsAndDynamicMethodMatchers; public Object proceed() throws Throwable { if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); // 执行目标方法 } Object interceptor = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptor instanceof MethodInterceptor) { return ((MethodInterceptor) interceptor).invoke(this); // 调用下一个拦截器 } return proceed(); // 继续链式调用 } }
9. 适配器模式(Adapter Pattern)
-
9.1 模式定义
将一个类的接口转换成客户希望的另外一个接口。
-
9.2 Spring 中的应用
适配器 目标接口 被适配者 说明 HandlerAdapterHandlerAdapterController/HttpRequestHandler/@RequestMapping方法统一适配不同类型的处理器 AdvisorAdapterAdvisorMethodBeforeAdvice/AfterReturningAdvice/ThrowsAdvice将 Advice 适配为 MethodInterceptor JpaVendorAdapterJpaVendorAdapterHibernate / EclipseLink / OpenJPA 适配不同 JPA 实现 java// HandlerAdapter:适配不同类型的处理器 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter { @Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) { // 将 @RequestMapping 方法适配为统一的 HandlerAdapter 接口 return invokeHandlerMethod(request, response, handlerMethod); } }
10. 其他设计模式
| 设计模式 | Spring 应用 | 说明 |
|---|---|---|
| 门面模式(Facade) | ApplicationContext |
封装 BeanFactory、资源加载、事件发布等复杂子系统 |
| 桥接模式(Bridge) | DataSource 与 Connection |
抽象与实现分离 |
| 组合模式(Composite) | CompositeCacheManager |
组合多个 CacheManager |
| 享元模式(Flyweight) | ConcurrentHashMap 缓存 BeanDefinition |
共享元数据对象 |
| 访问者模式(Visitor) | BeanDefinitionVisitor |
访问并修改 BeanDefinition |
| 解释器模式(Interpreter) | SpEL(Spring Expression Language) | 解析和执行表达式 |
| 建造者模式(Builder) | BeanDefinitionBuilder、RestTemplateBuilder |
链式构建复杂对象 |
| 原型模式(Prototype) | @Scope("prototype") |
每次获取创建新实例 |
11. 设计模式组合关系图
Spring 框架不是孤立使用设计模式,而是组合多种模式解决复杂问题:
AOP 实现 = 代理模式(JDK/CGLIB) + 责任链模式(拦截器链) + 装饰器模式(功能增强)
↓
事务管理 = 代理模式(创建代理) + 模板方法(事务边界) + 单例模式(TransactionManager)
↓
Spring MVC = 策略模式(HandlerMapping/HandlerAdapter) + 适配器模式(统一处理器接口) + 门面模式(DispatcherServlet)
↓
Spring Boot 自动配置 = 模板方法(AutoConfiguration) + 工厂模式(@Bean) + 条件模式(@Conditional)
12. 面试官追问与高分回答模板
-
追问 1:"Spring 用到了哪些设计模式?"
低分回答:"有单例、工厂、代理、装饰器、观察者、模板方法等。"(背诵式,没有具体落地)
高分回答:
"Spring 是设计模式的集大成者,我从源码层面梳理:
- 单例模式 :
DefaultSingletonBeanRegistry用ConcurrentHashMap管理单例 Bean;TransactionSynchronizationManager用 ThreadLocal 实现线程级单例。 - 工厂模式 :
BeanFactory是简单工厂,@Bean方法是工厂方法,FactoryBean(如SqlSessionFactoryBean)是抽象工厂。 - 代理模式 :AOP 使用 JDK 动态代理(有接口时)和 CGLIB 代理(无接口时),
DefaultAopProxyFactory根据条件选择。 - 装饰器模式 :
TransactionInterceptor为方法添加事务,HttpServletRequestWrapper包装请求对象。 - 观察者模式 :
ApplicationEvent+ApplicationListener实现事件驱动,@TransactionalEventListener支持事务绑定的事件。 - 模板方法模式 :
AbstractApplicationContext.refresh()定义容器启动骨架,JdbcTemplate封装 JDBC 操作的固定步骤。 - 策略模式 :
Resource(ClassPathResource/FileSystemResource)、AopProxy(JDK/CGLIB)、TransactionManager等。 - 责任链模式 :AOP 的
ReflectiveMethodInvocation拦截器链、Spring Security 的FilterChainProxy。 - 适配器模式 :
HandlerAdapter统一适配Controller/HttpRequestHandler/@RequestMapping方法。
关键是理解 Spring 如何组合这些模式解决复杂问题,如 AOP = 代理 + 责任链 + 装饰器。"
- 单例模式 :
-
追问 2:"Spring 的单例模式和你自己写的单例有什么区别?"
高分回答:
"传统单例模式(饿汉式/懒汉式/DCL)是在类内部控制实例化,通过静态字段和私有构造器实现。Spring 的单例是容器级管理:
维度 传统单例 Spring 单例 管理方 类自身 IoC 容器 生命周期 JVM 级别 容器级别 线程安全 DCL + volatile ConcurrentHashMap扩展性 低 高(支持 AOP 代理、生命周期回调) 作用域 全局唯一 容器内唯一(多容器可多个实例) Spring 的单例优势在于:容器统一管理生命周期(初始化、销毁)、支持 AOP 代理增强、可通过配置切换作用域。"
-
追问 3:"JdbcTemplate 用了什么设计模式?有什么好处?"
高分回答:
"
JdbcTemplate使用了模板方法模式。固定步骤(模板):获取连接 → 创建 Statement → 执行 SQL → 处理异常 → 释放资源(finally 中关闭 ResultSet/Statement/Connection)。
可变步骤(回调接口):
StatementCallback.doInStatement():自定义 Statement 操作ResultSetExtractor.extractData():自定义结果集处理RowMapper.mapRow():单行结果映射
好处:
- 消除样板代码:开发者只需关注 SQL 和结果处理,无需手动管理资源;
- 统一异常处理 :Spring 将 SQLException 转换为
DataAccessException体系; - 资源可靠释放:在 finally 中关闭资源,避免泄漏。"
-
追问 4:"Spring AOP 用到了哪些设计模式?"
高分回答:
"Spring AOP 是多种设计模式的组合:
- 代理模式:JDK 动态代理和 CGLIB 代理,为目标对象创建代理对象;
- 责任链模式 :
ReflectiveMethodInvocation将多个通知(@Before/@Around/@After)组织成调用链,按顺序执行; - 装饰器模式:每个通知都是一层装饰,为目标方法添加日志、事务、缓存等功能;
- 策略模式 :
DefaultAopProxyFactory根据条件选择 JDK 或 CGLIB 代理策略; - 适配器模式 :
AdvisorAdapter将MethodBeforeAdvice/AfterReturningAdvice适配为统一的MethodInterceptor。
这些模式的组合使得 AOP 既能灵活扩展(新增通知类型),又能保持核心逻辑简洁(代理创建 + 拦截器链执行)。"
-
追问 5:"Spring 事件机制是怎么实现的?用了什么设计模式?"
高分回答:
"Spring 事件机制基于观察者模式实现:
- 被观察者(Subject) :
ApplicationEventPublisher接口,ApplicationContext实现该接口; - 观察者(Observer) :
ApplicationListener接口,监听特定事件; - 事件(Event) :
ApplicationEvent子类,封装事件数据。
执行流程:
- 调用
publisher.publishEvent(event)发布事件; ApplicationEventMulticaster(默认SimpleApplicationEventMulticaster)遍历所有监听器;- 匹配事件类型的监听器调用
onApplicationEvent()。
扩展特性:
@EventListener注解驱动,无需实现接口;@Async实现异步事件处理;@TransactionalEventListener(phase = AFTER_COMMIT)实现事务绑定事件;ResolvableType支持泛型事件匹配。"
- 被观察者(Subject) :
-
追问 6:"Spring MVC 的 DispatcherServlet 用到了哪些设计模式?"
高分回答:
"
DispatcherServlet是设计模式的集大成者:- 门面模式(Facade) :
DispatcherServlet封装了 Spring MVC 的所有子系统(处理器映射、适配、视图解析等),对外提供统一的请求入口; - 策略模式 :
HandlerMapping(RequestMappingHandlerMapping、BeanNameUrlHandlerMapping)是 URL 映射策略,HandlerAdapter(RequestMappingHandlerAdapter、HttpRequestHandlerAdapter)是处理器适配策略; - 适配器模式 :
HandlerAdapter将不同类型的处理器(Controller接口、HttpRequestHandler接口、@RequestMapping注解方法)适配为统一的handle()接口; - 责任链模式 :
HandlerExecutionChain包含多个HandlerInterceptor,形成 preHandle → 目标方法 → postHandle → afterCompletion 的拦截器链; - 模板方法模式 :
FrameworkServlet定义了doGet/doPost的骨架,processRequest()→doService()→doDispatch(),子类(DispatcherServlet)重写具体步骤。
请求处理流程:
HTTP 请求 → DispatcherServlet.doDispatch() → HandlerMapping 获取 HandlerExecutionChain(含拦截器链) → HandlerAdapter.handle() 执行处理器 → ViewResolver 解析视图 → 渲染响应 ```" - 门面模式(Facade) :
13. 方案选型速查表
| 业务场景 | Spring 设计模式 | 核心类/注解 | 说明 |
|---|---|---|---|
| Bean 管理 | 单例 + 工厂 | DefaultSingletonBeanRegistry、@Bean |
容器统一管理生命周期 |
| 复杂对象创建 | 抽象工厂 | FactoryBean、SqlSessionFactoryBean |
封装复杂构建逻辑 |
| AOP 增强 | 代理 + 责任链 + 装饰器 | JdkDynamicAopProxy、ReflectiveMethodInvocation |
组合模式解决复杂增强 |
| JDBC 操作 | 模板方法 | JdbcTemplate |
固定步骤 + 回调接口 |
| 事件驱动 | 观察者 | ApplicationEvent、ApplicationListener |
松耦合消息传递 |
| URL 映射 | 策略 | HandlerMapping |
多种映射策略 |
| 处理器适配 | 适配器 | HandlerAdapter |
统一不同类型处理器 |
| 资源加载 | 策略 | ClassPathResource、FileSystemResource |
多种资源来源 |
| 事务管理 | 代理 + 模板方法 | TransactionInterceptor、TransactionTemplate |
声明式 + 编程式事务 |
| 请求过滤 | 责任链 | HandlerInterceptor、FilterChainProxy |
拦截器链/过滤器链 |
💡 面试官想要的满分总结:
Spring 框架是设计模式的百科全书,但面试中不能只是背诵模式名称,必须建立"模式 → 源码位置 → 工程价值"的完整链路。
最核心的模式组合有三组:
- IoC 容器 = 单例 + 工厂 + 模板方法 :
DefaultSingletonBeanRegistry管理单例,BeanFactory/FactoryBean创建对象,AbstractApplicationContext.refresh()定义容器启动骨架。- AOP = 代理 + 责任链 + 装饰器:代理模式创建代理对象,责任链模式组织多个通知,装饰器模式逐层增强功能。
- Spring MVC = 门面 + 策略 + 适配器 + 责任链 :
DispatcherServlet是门面,统一入口;HandlerMapping/HandlerAdapter是策略和适配器;HandlerExecutionChain是责任链。理解这些模式的关键是认识到:Spring 不是孤立使用模式,而是组合模式解决复杂问题。优秀的框架设计不是模式的堆砌,而是根据问题域选择最合适的模式组合,在扩展性和简洁性之间取得平衡。
觉得对您有帮助,麻烦 点点关注啦 ,您的关注是我创作的最大动力~ 🎯