1. 单例模式(结合 Spring @Component)
场景:配置中心、全局状态管理
Spring 实现:
java
// 自动注册为Spring Bean(默认单例)
@Component
public class AppConfig {
@Value("${server.port}")
private int port;
// 其他配置属性和方法
}
// 使用方式(依赖注入)
@Service
public class UserService {
@Autowired
private AppConfig appConfig;
public void startServer() {
System.out.println("启动服务器,端口:" + appConfig.getPort());
}
}
面试话术:
“在微服务项目中,我们用@Component
注解将配置类声明为 Spring Bean,默认就是单例模式。比如 AppConfig 类统一管理应用配置,通过@Value
注入配置值,所有需要使用配置的服务直接@Autowired
即可。Spring 容器帮我们保证了全局唯一实例,无需手动实现双重检查锁,代码更简洁。”
2. 工厂模式(结合 Spring FactoryBean)
场景:动态创建不同类型的数据源、Feign 客户端
Spring 实现:
java
// 数据源工厂(简化示例)
@Configuration
public class DataSourceConfig {
@Bean
public FactoryBean<DataSource> dataSourceFactory() {
return new DynamicDataSourceFactory();
}
}
// 自定义FactoryBean
public class DynamicDataSourceFactory implements FactoryBean<DataSource> {
@Override
public DataSource getObject() {
// 根据条件创建不同数据源(如主从库)
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/mydb")
.username("root")
.password("password")
.build();
}
@Override
public Class<?> getObjectType() {
return DataSource.class;
}
}
// 使用方式
@Service
public class DataService {
@Autowired
private DataSource dataSource;
}
面试话术:
“在分库分表场景中,我们用FactoryBean
接口实现动态数据源创建。比如根据租户 ID 选择主库或从库,通过自定义DynamicDataSourceFactory
,Spring 会自动调用getObject()
方法获取数据源实例。这种方式比传统工厂模式更优雅,与 Spring 的依赖注入体系无缝集成。”
3. 策略模式(结合 @Autowired+Map)
场景:支付方式、限流策略选择
Spring 实现:
java
// 支付策略接口
public interface PaymentStrategy {
void pay(BigDecimal amount);
}
// 支付宝策略
@Service("alipay")
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
System.out.println("支付宝支付:" + amount);
}
}
// 微信支付策略
@Service("wechatpay")
public class WechatPayStrategy implements PaymentStrategy {
@Override
public void pay(BigDecimal amount) {
System.out.println("微信支付:" + amount);
}
}
// 策略上下文(自动注入所有实现类)
@Service
public class PaymentService {
@Autowired
private Map<String, PaymentStrategy> strategyMap;
public void processPayment(String paymentType, BigDecimal amount) {
PaymentStrategy strategy = strategyMap.get(paymentType);
if (strategy != null) {
strategy.pay(amount);
} else {
throw new IllegalArgumentException("不支持的支付类型");
}
}
}
面试话术:
“在支付模块中,我们用策略模式结合 Spring 的自动注入特性。每种支付方式实现PaymentStrategy
接口并标记@Service
,通过@Autowired Map<String, PaymentStrategy>
可以自动收集所有策略实现类,Key 为 Bean 名称(如alipay
)。这种方式避免了传统策略模式中的大量if-else
,新增支付方式只需添加实现类,无需修改原有代码。”
4. 观察者模式(结合 Spring 事件机制)
场景:订单状态变更通知、异步事件处理
Spring 实现:
java
// 定义事件
public class OrderPaidEvent extends ApplicationEvent {
private final String orderId;
public OrderPaidEvent(Object source, String orderId) {
super(source);
this.orderId = orderId;
}
public String getOrderId() {
return orderId;
}
}
// 发布事件
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void payOrder(String orderId) {
// 处理支付逻辑
eventPublisher.publishEvent(new OrderPaidEvent(this, orderId));
}
}
// 监听事件(方式1:实现ApplicationListener)
@Component
public class SmsNotificationListener implements ApplicationListener<OrderPaidEvent> {
@Override
public void onApplicationEvent(OrderPaidEvent event) {
System.out.println("发送短信通知:订单" + event.getOrderId() + "已支付");
}
}
// 监听事件(方式2:@EventListener注解)
@Component
public class LoggingListener {
@EventListener
public void handleOrderPaid(OrderPaidEvent event) {
System.out.println("记录日志:订单" + event.getOrderId() + "已支付");
}
}
面试话术:
“在订单系统中,我们用 Spring 的事件机制替代传统观察者模式。当订单支付成功后,通过ApplicationEventPublisher
发布OrderPaidEvent
,短信通知和日志记录组件分别用@EventListener
注解监听该事件。这种方式比手动维护观察者列表更灵活,支持异步处理(通过@Async
注解),而且与 Spring 生态深度集成,例如可以结合事务实现事件的可靠发布。”
5. 装饰器模式(结合 Spring AOP)
场景:权限校验、日志增强、缓存切面
Spring 实现:
java
// 定义切面
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法开始:" + joinPoint.getSignature().getName());
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed(); // 执行原方法
long endTime = System.currentTimeMillis();
System.out.println("方法结束:" + joinPoint.getSignature().getName() +
",耗时:" + (endTime - startTime) + "ms");
return result;
}
}
面试话术:
“在性能监控场景中,我们用 Spring AOP 实现装饰器模式。通过@Around
注解定义切面,在方法执行前后添加日志记录和耗时统计逻辑,无需修改原有业务代码。这种方式比传统继承或组合更灵活,可以动态控制哪些方法需要增强,而且支持切入点表达式精确匹配目标方法。”
面试应答技巧
- 突出框架整合:强调如何利用 Spring 特性(如依赖注入、事件机制、AOP)简化设计模式实现,而非手动编码。
- 结合业务场景:举例说明在微服务、分布式系统中的应用(如 Feign 客户端工厂、Sentinel 限流策略)。
- 对比传统方式:指出相比 “手搓” 设计模式,Spring 提供的方案更优雅、更符合开闭原则。
例如:
“在我们的微服务项目中,服务间通信使用 Feign 客户端。当需要根据环境动态切换服务 URL 时,我们实现了
FeignClientFactoryBean
,利用 Spring 的工厂机制和配置中心(Nacos),根据不同环境加载不同的服务地址。这种方式比硬编码 URL 更灵活,符合工厂模式的思想,同时充分利用了 Spring 的生态优势。”