完整教程:Spring中常用的设计模式
非常好!为了帮助你更直观、深入地理解 Spring 中常用的设计模式,下面我将结合 具体的代码示例,逐一说明这些设计模式在 Spring 中是如何体现和应用的,包括 关键类、注解、配置 和 实际使用场景。
一、IoC(控制反转)与 DI(依赖注入)【核心思想,非 GoF 模式】
模式说明:
将对象的创建权和依赖管理交给 Spring 容器,而不是开发者手动 new。
✅ 代码示例:
@Service
public class UserService {
// 由 Spring 自动注入,不用手动 new
@Autowired
private UserRepository userRepository;
public void addUser(String name) {
userRepository.save(name);
}
}
@Repository
public class UserRepository {
public void save(String name) {
System.out.println("保存用户: " + name);
}
}
说明:
UserService依赖UserRepository,但不需要手动创建,而是由 Spring 容器自动注入(DI),这就是 控制反转(IoC) 的体现。
二、工厂模式(Factory Pattern)
模式说明:
对象的创建由专门的工厂管理,而不是直接使用 new。
✅ 代码示例:Spring 的 BeanFactory / ApplicationContext
Spring 自带的核心容器就是工厂模式的实现:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从工厂(容器)中获取 Bean,而不是手动 new
UserService userService = context.getBean(UserService.class);
userService.addUser("小明");
说明:
ApplicationContext是 Spring 提供的一个高级“工厂”,负责管理所有 Bean 的创建和依赖注入。
三、单例模式(Singleton Pattern)
模式说明:
确保一个类只有一个实例,并提供全局访问点。
✅ 代码示例:Spring 默认的 Bean 作用域就是单例
@Service
public class CounterService {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
测试代码:
@Autowired
private CounterService counterService1;
@Autowired
private CounterService counterService2;
System.out.println(counterService1.getCount()); // 0
counterService1.increment();
System.out.println(counterService2.getCount()); // 1,说明是同一个实例
说明: Spring 中默认的 Bean 作用域是 singleton(单例),即整个容器中只存在一个实例,所有注入的地方都共享该对象。
四、代理模式(Proxy Pattern)
模式说明:
为对象提供一个代理,以控制对这个对象的访问,常用于 AOP。
✅ 代码示例:使用 @Transactional 注解(底层使用代理实现事务)
@Service
public class OrderService {
@Transactional // 由 Spring AOP 生成代理,实现事务管理
public void createOrder(String orderId) {
System.out.println("创建订单:" + orderId);
// 模拟异常
if (true) throw new RuntimeException("模拟异常,触发回滚");
}
}
说明: 当你使用
@Transactional,Spring 会为OrderService创建一个 代理对象,在方法执行前后加入事务控制逻辑,而你无需手动编写事务代码。
底层原理: 使用 JDK 动态代理 或 CGLIB 生成代理类,这就是 代理模式 的实际应用。
五、模板方法模式(Template Method Pattern)
模式说明:
定义一个操作中的算法骨架,将某些步骤延迟到子类或具体实现中。
✅ 代码示例:JdbcTemplate(简化 JDBC 操作)
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<String> findAllUsernames() {
return jdbcTemplate.queryForList(
"SELECT username FROM users",
String.class
);
}
}
说明:
JdbcTemplate封装了 JDBC 的连接获取、异常处理、资源释放等重复逻辑,开发者只需要关注 SQL 语句和结果处理,这就是 模板方法模式 的典型应用。
六、观察者模式(Observer Pattern)
模式说明:
定义对象间的一对多依赖关系,当一个对象状态发生变化时,所有依赖它的对象都会收到通知。
✅ 代码示例:Spring 的事件机制(ApplicationEvent / Listener)
- 定义事件:
public class UserRegisteredEvent extends ApplicationEvent {
private String username;
public UserRegisteredEvent(Object source, String username) {
super(source);
this.username = username;
}
public String getUsername() {
return username;
}
}
- 发布事件:
@Service
public class UserService {
@Autowired
private ApplicationContext applicationContext;
public void registerUser(String username) {
System.out.println("用户注册: " + username);
// 发布事件
applicationContext.publishEvent(new UserRegisteredEvent(this, username));
}
}
- 监听事件:
@Component
public class UserRegisteredListener implements ApplicationListener<UserRegisteredEvent> {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
System.out.println("收到用户注册事件,用户名:" + event.getUsername());
}
}
说明: 这是典型的 观察者模式,事件发布者不关心谁监听,监听者自动收到通知,实现解耦。
七、适配器模式(Adapter Pattern)
模式说明:
将一个类的接口转换成客户端所期望的另一个接口。
✅ 代码示例:Spring MVC 中的 HandlerAdapter
虽然我们一般不直接使用,但 Spring MVC 内部使用 HandlerAdapter 将不同类型的 Controller(如 @Controller、HttpRequestHandler)适配成统一的处理逻辑。
简化理解:
- 你写了一个
@RestController,但底层 Spring 需要通过适配器将其方法调用与 HTTP 请求处理逻辑对接起来。 - 每种 Controller 类型都有对应的 Adapter 实现,如
RequestMappingHandlerAdapter。
说明: 这是典型的 适配器模式,用于统一处理不同接口实现。
✅ Spring MVC 中的 HandlerAdapter(处理 HTTP 请求的核心)
在 Spring MVC 中,开发者通常使用 @Controller 或 @RestController 定义控制器方法,例如:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
return "User " + id;
}
}
但是,Spring 底层并不是直接调用你的 Controller 方法,而是通过一个中间层——HandlerAdapter(处理器适配器),将不同类型的处理器(如基于注解的 @Controller、传统的 HttpRequestHandler、Servlet 等)适配成统一的处理逻辑,最后执行目标方法并返回结果。
适配器模式在 Spring MVC 中的体现(源码级别简化理解)
虽然我们一般不会自己去实现 HandlerAdapter,但 Spring 提供了多个内置的适配器,比如:
RequestMappingHandlerAdapter:处理@RequestMapping注解的控制器方法(也就是我们最常用的@RestController/@Controller)。HttpRequestHandlerAdapter:处理实现了HttpRequestHandler接口的处理器。SimpleControllerHandlerAdapter:处理实现了Controller接口的旧式控制器。
适配器模式在这里的作用总结:
| 角色 | 说明 | 对应 Spring 中的实现 |
|---|---|---|
| Handler(处理器) | 实际处理请求的对象,但类型可能不同 | @Controller 方法、HttpRequestHandler 等 |
| HandlerAdapter(适配器) | 将不同处理器适配成统一的调用方式 | RequestMappingHandlerAdapter、HttpRequestHandlerAdapter |
| Dispatcher(调度器) | 根据处理器类型选择合适的适配器来执行 | DispatcherServlet |
Spring MVC 的核心调度逻辑中,正是通过多个 HandlerAdapter 实现了对不同 Controller 类型的适配,这就是适配器模式的典型应用。
✅ 总结一句话:
在 Spring MVC 中,HandlerAdapter 是适配器模式的典型应用,它让不同类型的处理器(如注解控制器、传统控制器)能够通过统一的接口被调度和执行,从而实现灵活、可扩展的请求处理机制。
八、策略模式(Strategy Pattern)
模式说明:
定义一组算法,将每个算法封装起来,并使它们可以互相替换。
✅ 代码示例:Spring 事务管理策略
Spring 根据不同的数据源,使用不同的 PlatformTransactionManager 实现类,如:
DataSourceTransactionManager(用于 JDBC)HibernateTransactionManager(用于 Hibernate)JpaTransactionManager(用于 JPA)
Spring 会根据你配置的事务管理器,动态选择合适的策略来管理事务。
✅ 配置示例:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource); // 选择 JDBC 事务策略
}
说明: 不同的数据访问技术,使用不同的策略实现,但对外提供统一的编程模型,这就是 策略模式。
九、原型模式(Prototype Pattern)
模式说明:
每次获取 Bean 时都创建一个新的实例,而不是复用。
✅ 代码示例:设置 Bean 为 Prototype 作用域
@Component
@Scope("prototype") // 每次获取新实例
public class PrototypeBean {
private UUID id = UUID.randomUUID();
public UUID getId() {
return id;
}
}
测试代码:
@Autowired
private ApplicationContext context;
PrototypeBean bean1 = context.getBean(PrototypeBean.class);
PrototypeBean bean2 = context.getBean(PrototypeBean.class);
System.out.println(bean1.getId()); // UUID1
System.out.println(bean2.getId()); // UUID2,不一样!
说明: 每次调用
getBean()都生成新的对象,适用于有状态的 Bean。
总结:Spring 常用设计模式与代码对照表
| 设计模式 | 说明 | Spring 中的体现 | 代码关键词/注解 |
|---|---|---|---|
| IoC / DI | 控制反转与依赖注入 | Bean 由 Spring 管理,自动注入 | @Autowired, @Service |
| 工厂模式 | 统一创建对象 | ApplicationContext, BeanFactory | context.getBean() |
| 单例模式 | 一个类只有一个实例 | 默认 Bean 作用域 | 无特别配置,就是单例 |
| 代理模式 | 方法增强、AOP 实现 | @Transactional, AOP 代理 | @Aspect, @Around |
| 模板方法模式 | 封装固定流程 | JdbcTemplate, RestTemplate | jdbcTemplate.query(...) |
| 观察者模式 | 事件驱动 | ApplicationEvent, ApplicationListener | 事件发布与监听 |
| 适配器模式 | 接口转换 | HandlerAdapter(Spring MVC) | 适配不同 Controller |
| 策略模式 | 算法替换 | 事务管理策略、HandlerMapping | PlatformTransactionManager |
| 原型模式 | 每次获取新对象 | @Scope("prototype") | 每次 getBean() 不一样 |
浙公网安备 33010602011771号