Spring与JDK设计模式实践解析
框架中的设计模式实践:Spring与JDK的经典实现
设计模式是软件开发中的最佳实践总结,在Java生态中,Spring框架和JDK自身都大量运用了各种设计模式。本文将深入剖析这些经典实现,帮助开发者理解模式的实际应用场景。
一、Spring框架中的模式应用
1. 工厂模式(BeanFactory)
概念:
BeanFactory是Spring IoC容器的核心接口,它实现了工厂模式,负责创建和管理应用中的对象(称为beans)。
实现原理:
// 典型使用方式
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
MyService service = context.getBean(MyService.class);
mermaid类图:
实践建议:
- 优先使用
ApplicationContext
而非直接使用BeanFactory
,因为它提供了更多企业级功能 - 理解bean的作用域(singleton/prototype等)对系统性能的影响
- 利用
@Configuration
和@Bean
实现自定义工厂逻辑
2. 代理模式(AOP实现)
概念:
Spring AOP通过代理模式实现横切关注点的模块化,主要分为JDK动态代理和CGLIB代理两种方式。
实现对比:
特性 | JDK动态代理 | CGLIB代理 |
---|---|---|
原理 | 基于接口 | 基于类继承 |
性能 | 调用快,创建慢 | 创建快,调用稍慢 |
限制 | 必须实现接口 | 无法代理final方法 |
示例代码:
// 定义切面
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Executing: " + joinPoint.getSignature());
}
}
实践建议:
- 对于性能敏感场景,考虑使用AspectJ编译时织入
- 谨慎选择切入点表达式,避免过度拦截影响性能
- 代理方法内部调用不会触发AOP,这是常见陷阱
3. 模板方法(JdbcTemplate)
概念:
JdbcTemplate是模板方法模式的经典实现,封装了JDBC操作的固定流程,开发者只需关注SQL和结果处理。
核心流程:
- 获取连接
- 创建语句
- 执行操作
- 处理结果
- 处理异常
- 释放资源
示例代码:
public List<User> findAll() {
return jdbcTemplate.query("SELECT * FROM users", (rs, rowNum) -> {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
return user;
});
}
实践建议:
- 利用
NamedParameterJdbcTemplate
提高SQL可读性 - 对于复杂映射,考虑使用
RowMapper
实现类而非lambda - 批量操作使用
batchUpdate()
方法显著提高性能
二、JDK内置的模式实现
1. 观察者模式(java.util.Observable)
概念:
Observable类和Observer接口构成了JDK对观察者模式的实现,允许对象间建立发布-订阅关系。
演进现状:
- Java 9开始
Observable
被标记为过时 - 现代开发推荐使用
java.beans.PropertyChangeSupport
或反应式流(如RxJava)
经典实现:
class WeatherData extends Observable {
private float temperature;
public void setTemperature(float temp) {
this.temperature = temp;
setChanged(); // 标记状态已改变
notifyObservers(); // 通知观察者
}
}
class Display implements Observer {
@Override
public void update(Observable o, Object arg) {
// 更新显示逻辑
}
}
实践建议:
- 在新项目中避免直接使用
Observable/Observer
- 考虑使用
PropertyChangeListener
或反应式编程库 - 注意线程安全问题,观察者通知通常发生在发布者线程
2. 迭代器模式(java.util.Iterator)
概念:
迭代器模式提供了一种顺序访问集合元素的方法,而不暴露其底层表示。
JDK演进:
- Java 5引入
Iterable
接口和增强for循环 - Java 8引入
forEachRemaining
默认方法
并发考虑:
List<String> list = Collections.synchronizedList(new ArrayList<>());
// 需要客户端加锁的迭代
synchronized(list) {
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
实践建议:
- 对
ArrayList
等非线程安全集合,使用CopyOnWriteArrayList
避免并发修改异常 - Java 8+推荐使用
forEach
方法简化迭代代码 - 实现自定义集合时,考虑实现
Spliterator
以支持并行流
3. 装饰器模式(java.io包)
概念:
装饰器模式通过包装原始对象动态添加功能,java.io包是这一模式的典型应用。
类结构:
正确用法:
// 多层装饰
try (InputStream is = new BufferedInputStream(
new GZIPInputStream(
new FileInputStream("data.gz")))) {
// 读取处理
}
实践建议:
- 总是使用try-with-resources确保流正确关闭
- 注意装饰顺序,比如缓冲流应该包装在最外层
- 对于NIO场景,考虑使用
Channels
和Buffers
获得更好性能
三、模式选择的最佳实践
框架优先原则:
- 优先使用Spring或JDK内置的模式实现
- 避免重复造轮子,但需理解底层原理
性能考量:
// 不好的做法:每次调用都创建新代理 public void process() { Service proxy = createProxy(realService); // 昂贵操作 proxy.doSomething(); }
可测试性:
- 依赖注入使模式实现更易测试
- 使用Mockito等工具测试代理行为
现代Java特性结合:
// 使用Lambda简化观察者模式 eventStream.subscribe(event -> { // 处理事件 });
理解这些模式在框架中的实现,不仅能帮助我们更好地使用这些框架,还能在自定义开发中做出更合适的设计决策。记住,模式是手段而非目的,应根据实际场景灵活运用。