问题
Spring中用到了哪些设计模式?
答案
1. 核心概念
Spring框架是设计模式的集大成者,通过巧妙运用多种设计模式实现了IoC(控制反转)、AOP(面向切面编程)等核心特性。掌握这些设计模式有助于深入理解Spring源码和架构设计。
2. Spring中的核心设计模式
2.1 单例模式(Singleton Pattern)
应用场景:Spring Bean默认作用域
实现方式:
// Spring通过ConcurrentHashMap缓存单例Bean
public class DefaultSingletonBeanRegistry {
// 一级缓存:存放完全初始化的单例Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
public Object getSingleton(String beanName) {
// 双重检查锁(DCL)保证线程安全
Object singletonObject = singletonObjects.get(beanName);
if (singletonObject == null) {
synchronized (this.singletonObjects) {
singletonObject = singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = createBean(beanName);
singletonObjects.put(beanName, singletonObject);
}
}
}
return singletonObject;
}
}
优势:
- 减少对象创建开销
- 全局唯一实例,便于共享资源
Bean作用域配置:
// 单例(默认)
@Component
@Scope("singleton")
public class UserService {}
// 原型(每次请求创建新实例)
@Component
@Scope("prototype")
public class OrderService {}
2.2 工厂模式(Factory Pattern)
应用场景:BeanFactory和ApplicationContext创建Bean
三种工厂模式的应用:
简单工厂:
// BeanFactory接口
public interface BeanFactory {
Object getBean(String name);
<T> T getBean(String name, Class<T> requiredType);
}
工厂方法:
// FactoryBean接口:自定义Bean的创建逻辑
public class CarFactoryBean implements FactoryBean<Car> {
@Override
public Car getObject() throws Exception {
// 复杂的创建逻辑
Car car = new Car();
car.setEngine(new Engine());
car.setWheel(new Wheel());
return car;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
抽象工厂:
// ApplicationContext体系
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
ApplicationContext context = new FileSystemXmlApplicationContext("C:/beans.xml");
2.3 代理模式(Proxy Pattern)
应用场景:AOP的核心实现机制
两种代理实现:
JDK动态代理(基于接口):
// Spring AOP使用JDK动态代理
public class JdkDynamicAopProxy implements InvocationHandler {
private final Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
System.out.println("Before method: " + method.getName());
// 执行目标方法
Object result = method.invoke(target, args);
// 后置增强
System.out.println("After method: " + method.getName());
return result;
}
}
CGLIB动态代理(基于子类):
// 目标类无接口时,Spring使用CGLIB
public class CglibAopProxy implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
System.out.println("CGLIB Before: " + method.getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("CGLIB After: " + method.getName());
return result;
}
}
实际应用:
@Aspect
@Component
public class LogAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Object result = joinPoint.proceed(); // 代理调用目标方法
System.out.println("方法执行后");
return result;
}
}
2.4 模板方法模式(Template Method Pattern)
应用场景:JdbcTemplate、RestTemplate、TransactionTemplate
核心思想:定义算法骨架,将某些步骤延迟到子类实现
JdbcTemplate示例:
public class JdbcTemplate {
// 模板方法:定义执行流程
public <T> T execute(StatementCallback<T> action) {
Connection con = null;
Statement stmt = null;
try {
// 1. 获取连接
con = DataSourceUtils.getConnection(dataSource);
// 2. 创建Statement
stmt = con.createStatement();
// 3. 执行回调(变化部分由用户实现)
T result = action.doInStatement(stmt);
return result;
} catch (SQLException ex) {
// 4. 异常处理
throw translateException(ex);
} finally {
// 5. 释放资源
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, dataSource);
}
}
}
使用示例:
jdbcTemplate.execute(new StatementCallback<Integer>() {
@Override
public Integer doInStatement(Statement stmt) throws SQLException {
return stmt.executeUpdate("UPDATE user SET name = 'Alice' WHERE id = 1");
}
});
2.5 观察者模式(Observer Pattern)
应用场景:Spring事件机制(ApplicationEvent和ApplicationListener)
实现示例:
自定义事件:
// 1. 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private Order order;
public OrderCreatedEvent(Object source, Order order) {
super(source);
this.order = order;
}
public Order getOrder() {
return order;
}
}
事件监听器:
// 2. 定义监听器
@Component
public class OrderEventListener implements ApplicationListener<OrderCreatedEvent> {
@Override
public void onApplicationEvent(OrderCreatedEvent event) {
Order order = event.getOrder();
System.out.println("订单创建事件触发:" + order.getId());
// 发送邮件、扣减库存等操作
}
}
// 或使用@EventListener注解
@Component
public class AnotherListener {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
System.out.println("处理订单:" + event.getOrder().getId());
}
}
发布事件:
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder(Order order) {
// 保存订单
orderRepository.save(order);
// 发布事件
publisher.publishEvent(new OrderCreatedEvent(this, order));
}
}
内置事件:
ContextRefreshedEvent:容器刷新完成ContextStartedEvent:容器启动ContextStoppedEvent:容器停止ContextClosedEvent:容器关闭
2.6 策略模式(Strategy Pattern)
应用场景:Resource加载策略、事务传播行为
Resource加载策略:
public interface Resource {
InputStream getInputStream() throws IOException;
}
// 不同的加载策略
public class ClassPathResource implements Resource { }
public class FileSystemResource implements Resource { }
public class UrlResource implements Resource { }
// ResourceLoader根据路径前缀选择策略
public class DefaultResourceLoader {
public Resource getResource(String location) {
if (location.startsWith("classpath:")) {
return new ClassPathResource(location);
} else if (location.startsWith("file:")) {
return new FileSystemResource(location);
} else if (location.startsWith("http:")) {
return new UrlResource(location);
}
return new ClassPathResource(location);
}
}
实际应用:
// 业务场景:支付策略
public interface PaymentStrategy {
void pay(BigDecimal amount);
}
@Component("alipay")
public class AlipayStrategy implements PaymentStrategy {
public void pay(BigDecimal amount) {
System.out.println("支付宝支付:" + amount);
}
}
@Component("wechat")
public class WechatPayStrategy implements PaymentStrategy {
public void pay(BigDecimal amount) {
System.out.println("微信支付:" + amount);
}
}
@Service
public class PaymentService {
@Autowired
private Map<String, PaymentStrategy> strategies; // Spring自动注入所有实现
public void pay(String type, BigDecimal amount) {
PaymentStrategy strategy = strategies.get(type);
strategy.pay(amount);
}
}
2.7 适配器模式(Adapter Pattern)
应用场景:SpringMVC的HandlerAdapter
原理:
// SpringMVC支持多种Controller写法
// 1. 实现Controller接口
public class OldStyleController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) {
return new ModelAndView("index");
}
}
// 2. 使用@RequestMapping注解
@Controller
public class NewStyleController {
@RequestMapping("/hello")
public String hello() {
return "hello";
}
}
// HandlerAdapter适配不同的Controller实现
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request,
HttpServletResponse response,
Object handler);
}
// 适配实现Controller接口的控制器
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
public ModelAndView handle(..., Object handler) {
return ((Controller) handler).handleRequest(request, response);
}
}
// 适配@RequestMapping注解的控制器
public class RequestMappingHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof HandlerMethod);
}
public ModelAndView handle(..., Object handler) {
// 通过反射调用@RequestMapping方法
return invokeHandlerMethod(request, response, (HandlerMethod) handler);
}
}
2.8 装饰器模式(Decorator Pattern)
应用场景:BeanWrapper、HttpServletRequestWrapper
BeanWrapper示例:
// BeanWrapper为Bean提供属性访问和类型转换功能
BeanWrapper bw = new BeanWrapperImpl(new User());
bw.setPropertyValue("name", "Alice");
bw.setPropertyValue("age", "30"); // 自动类型转换String -> Integer
// 装饰器模式:为原始Bean增强功能
public class BeanWrapperImpl implements BeanWrapper {
private Object wrappedObject;
private PropertyAccessor propertyAccessor; // 装饰功能
public void setPropertyValue(String propertyName, Object value) {
// 类型转换
Object convertedValue = convertIfNecessary(value, getPropertyType(propertyName));
// 设置属性
propertyAccessor.setPropertyValue(wrappedObject, propertyName, convertedValue);
}
}
实际应用:
// Spring MVC中包装HttpServletRequest
public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
private final ByteArrayOutputStream cachedContent = new ByteArrayOutputStream();
@Override
public ServletInputStream getInputStream() throws IOException {
// 装饰原始InputStream,缓存内容供后续读取
return new CachedServletInputStream(super.getInputStream());
}
}
2.9 责任链模式(Chain of Responsibility Pattern)
应用场景:Spring Security过滤器链、AOP拦截器链
Spring Security示例:
// 多个安全过滤器组成责任链
public class FilterChainProxy {
private List<SecurityFilterChain> filterChains;
public void doFilter(ServletRequest request, ServletResponse response) {
// 按顺序执行过滤器
VirtualFilterChain chain = new VirtualFilterChain(filters);
chain.doFilter(request, response);
}
}
// 过滤器链执行
UsernamePasswordAuthenticationFilter // 用户名密码认证
-> BasicAuthenticationFilter // Basic认证
-> CsrfFilter // CSRF保护
-> ExceptionTranslationFilter // 异常处理
-> FilterSecurityInterceptor // 权限控制
2.10 建造者模式(Builder Pattern)
应用场景:RestTemplateBuilder、UriComponentsBuilder
示例:
// RestTemplate构建
RestTemplate restTemplate = new RestTemplateBuilder()
.rootUri("https://api.example.com")
.basicAuthentication("user", "password")
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(10))
.build();
// URI构建
UriComponents uri = UriComponentsBuilder.newInstance()
.scheme("https")
.host("example.com")
.path("/api/users/{id}")
.queryParam("active", true)
.buildAndExpand(1001);
// 结果:https://example.com/api/users/1001?active=true
3. 设计模式在Spring中的协作
实际场景:用户登录
// 1. 单例模式:UserService是单例Bean
@Service
public class UserService {
// 2. 工厂模式:通过ApplicationContext创建Bean
@Autowired
private UserRepository userRepository;
// 3. 模板方法模式:JdbcTemplate封装数据库操作
@Autowired
private JdbcTemplate jdbcTemplate;
// 4. 代理模式:@Transactional通过AOP实现事务管理
@Transactional
public User login(String username, String password) {
// 5. 策略模式:不同的加密策略
PasswordEncoder encoder = new BCryptPasswordEncoder();
User user = userRepository.findByUsername(username);
if (encoder.matches(password, user.getPassword())) {
// 6. 观察者模式:发布登录成功事件
publisher.publishEvent(new LoginSuccessEvent(this, user));
return user;
}
throw new BadCredentialsException("密码错误");
}
}
4. 面试答题总结
标准回答模板:
Spring框架中应用了大量设计模式,主要包括:
- 单例模式:Spring Bean默认是单例,通过ConcurrentHashMap缓存
- 工厂模式:BeanFactory、FactoryBean、ApplicationContext创建和管理Bean
- 代理模式:AOP的核心实现(JDK动态代理 + CGLIB)
- 模板方法模式:JdbcTemplate、RestTemplate定义算法骨架
- 观察者模式:Spring事件机制(ApplicationEvent + ApplicationListener)
- 策略模式:Resource加载、事务传播行为
- 适配器模式:SpringMVC的HandlerAdapter适配不同Controller
- 装饰器模式:BeanWrapper为Bean增强属性访问能力
- 责任链模式:Spring Security过滤器链、AOP拦截器链
- 建造者模式:RestTemplateBuilder、UriComponentsBuilder
核心价值:
- 提高代码复用性和可维护性
- 降低模块间耦合
- 使框架具备良好的扩展性
常见追问:
- Spring AOP使用哪种代理? → 默认JDK动态代理(基于接口),无接口时用CGLIB(基于子类)
- 单例Bean是否线程安全? → 取决于Bean本身,Spring只保证单例,不保证线程安全(无状态Bean是线程安全的)
- 模板方法模式和策略模式的区别? → 模板方法定义算法骨架(继承),策略模式封装算法族(组合)