设计模式在 Spring/JDK 中的应用汇总
面试官:你说了解设计模式,那你能说说 Spring 框架里用了哪些设计模式吗?
你:Spring 框架大量使用了设计模式,核心的有工厂模式(BeanFactory)、单例模式(Bean 默认 scope)、代理模式(AOP)、模板方法模式(JdbcTemplate)、观察者模式(ApplicationEvent)等。
面试官:能具体说说 BeanFactory 和 FactoryBean 的区别吗?它们各自体现了什么模式?
这道题是设计模式面试的「综合考题」。能流利说出 6-8 个有源码支撑的例子,并区分易混淆的概念,就能让面试官印象深刻。
链式追问一:Spring 核心模式
Section titled “链式追问一:Spring 核心模式”Q1:Spring 中使用了哪些设计模式?各自的应用场景是什么?必考
Section titled “Q1:Spring 中使用了哪些设计模式?各自的应用场景是什么?”Spring 核心设计模式汇总:
| 设计模式 | Spring 应用 | 核心类/注解 | 作用 |
|---|---|---|---|
| 工厂模式 | Bean 创建 | BeanFactory、FactoryBean | 封装对象创建逻辑 |
| 单例模式 | Bean 作用域 | DefaultSingletonBeanRegistry | 容器级单例 |
| 代理模式 | AOP、事务 | JdkDynamicAopProxy、CglibAopProxy | 方法拦截增强 |
| 模板方法 | 样板代码封装 | JdbcTemplate、RestTemplate | 定义算法骨架 |
| 观察者模式 | 事件机制 | ApplicationEvent、@EventListener | 解耦事件发布和监听 |
| 策略模式 | 资源加载 | ResourceLoader | 根据路径选择加载策略 |
| 责任链模式 | 请求处理 | Filter、Interceptor | 链式处理请求 |
| 装饰器模式 | Bean 增强 | BeanWrapper | 动态增强 Bean 功能 |
| 适配器模式 | 处理器适配 | HandlerAdapter | 统一不同处理器接口 |
| 建造者模式 | 对象构建 | BeanDefinitionBuilder | 分步构建复杂对象 |
Spring 模式应用架构:
┌────────────────────────────────────────────────┐│ Spring 框架的设计模式应用 │├────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────┐ ││ │ IoC 容器 │ ││ │ ├── 工厂模式(BeanFactory) │ ││ │ ├── 单例模式(Singleton) │ ││ │ └── 建造者模式(BeanDefinition) │ ││ └─────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────┐ ││ │ AOP │ ││ │ ├── 代理模式(JDK/CGLIB) │ ││ │ ├── 责任链模式(Advice 链) │ ││ │ └── 策略模式(Pointcut) │ ││ └─────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────┐ ││ │ MVC │ ││ │ ├── 适配器模式(HandlerAdapter) │ ││ │ ├── 责任链模式(Interceptor) │ ││ │ └── 观察者模式(事件监听) │ ││ └─────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────┐ ││ │ Template │ ││ │ ├── 模板方法(JdbcTemplate) │ ││ │ └── 外观模式(统一入口) │ ││ └─────────────────────────────────────┘ ││ │└────────────────────────────────────────────────┘Q2:BeanFactory 和 FactoryBean 的区别?必考
Section titled “Q2:BeanFactory 和 FactoryBean 的区别?”核心区别:
| 对比维度 | BeanFactory | FactoryBean |
|---|---|---|
| 定义 | Spring 容器的顶层接口 | 用户自定义 Bean 创建的接口 |
| 作用 | 生产和管理所有 Bean | 用户自定义单个 Bean 的创建逻辑 |
| 谁来用 | Spring 框架 | 开发者 |
| 模式 | 工厂模式 | 工厂方法模式 |
| 典型应用 | 所有 Bean 的管理 | MyBatis SqlSessionFactory |
BeanFactory 源码:
// Spring 容器的顶层接口public interface BeanFactory { // 获取 Bean Object getBean(String name) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException;
// 判断 Bean 是否存在 boolean containsBean(String name);
// 判断是否单例 boolean isSingleton(String name);}
// 实现类:DefaultListableBeanFactorypublic class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory { // 单例缓存 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// Bean 定义注册表 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
@Override public Object getBean(String name) { // 1. 从缓存获取(单例) Object bean = singletonObjects.get(name); if (bean != null) { return bean; }
// 2. 创建 Bean BeanDefinition bd = beanDefinitionMap.get(name); bean = createBean(name, bd);
// 3. 缓存单例 if (bd.isSingleton()) { singletonObjects.put(name, bean); }
return bean; }}FactoryBean 源码:
// 用户自定义 Bean 创建逻辑public interface FactoryBean<T> { // 返回创建的对象 T getObject() throws Exception;
// 返回对象类型 Class<?> getObjectType();
// 是否单例(默认 true) default boolean isSingleton() { return true; }}
// 典型应用:MyBatis 整合 Springpublic class SqlSessionFactoryBean implements FactoryBean<SqlSession>, InitializingBean { private DataSource dataSource; private Configuration configuration;
@Override public SqlSession getObject() throws Exception { SqlSessionFactory factory = new SqlSessionFactoryBuilder() .build(configuration); return factory.openSession(); }
@Override public Class<?> getObjectType() { return SqlSession.class; }
@Override public void afterPropertiesSet() { // 初始化 Configuration configuration = new Configuration(); configuration.setDataSource(dataSource); }}
// Spring 配置@Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean; // 返回 FactoryBean,Spring 会调用 getObject() 获取真正的 Bean}
// 获取 BeanSqlSession session = applicationContext.getBean(SqlSession.class); // 获取的是 SqlSession,不是 SqlSessionFactoryBeanFactoryBean 的使用场景:
| 场景 | 示例 | 说明 |
|---|---|---|
| 框架整合 | SqlSessionFactoryBean | MyBatis 整合 Spring |
| 动态代理 | ProxyFactoryBean | 创建代理对象 |
| 复杂对象 | FactoryBean<Object> | 需要复杂初始化逻辑的对象 |
Q3:Spring AOP 使用了哪些设计模式?必考
Section titled “Q3:Spring AOP 使用了哪些设计模式?”Spring AOP 的设计模式:
┌────────────────────────────────────────────────┐│ Spring AOP 的设计模式应用 │├────────────────────────────────────────────────┤│ ││ 1. 代理模式 ││ ├── JDK 动态代理(有接口) ││ └── CGLIB 代理(无接口) ││ └── 核心类:JdkDynamicAopProxy ││ CglibAopProxy ││ ││ 2. 责任链模式 ││ ├── Advice 链(通知链) ││ └── MethodInterceptor 链式调用 ││ └── ReflectiveMethodInvocation ││ ││ 3. 策略模式 ││ ├── Pointcut(切点) ││ └── 不同匹配策略 ││ └── AspectJExpressionPointcut ││ ││ 4. 模板方法模式 ││ ├── AbstractAutoProxyCreator ││ └── 定义代理创建流程 ││ │└────────────────────────────────────────────────┘AOP 代理创建源码:
// 代理创建的核心类public class DefaultAopProxyFactory implements AopProxyFactory { @Override public AopProxy createAopProxy(AdvisedSupport config) { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { // 使用 CGLIB 代理 return new CglibAopProxy(config); } else { // 使用 JDK 动态代理 return new JdkDynamicAopProxy(config); } }}
// JDK 动态代理实现final class JdkDynamicAopProxy implements AopProxy, InvocationHandler { private final AdvisedSupport advised;
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 1. 获取拦截器链(责任链) List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 2. 创建方法调用对象 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 3. 执行责任链 return invocation.proceed(); }}
// 责任链调用public class ReflectiveMethodInvocation implements ProxyMethodInvocation { private final List<?> interceptorsAndDynamicMethodMatchers; private int currentInterceptorIndex = -1;
@Override public Object proceed() throws Throwable { // 所有拦截器都执行完了,调用目标方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }
// 获取下一个拦截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 执行拦截器 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); }}
// MethodInterceptor 示例public class LoggingInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("方法调用前:" + invocation.getMethod().getName());
Object result = invocation.proceed(); // 继续执行责任链
System.out.println("方法调用后:" + invocation.getMethod().getName()); return result; }}责任链模式图示:
┌────────────────────────────────────────────────┐│ AOP 责任链执行流程 │├────────────────────────────────────────────────┤│ ││ MethodInvocation.proceed() ││ │ ││ ├── Interceptor1.invoke() ││ │ ├── 前置逻辑 ││ │ ├── invocation.proceed() ││ │ │ │ ││ │ │ ├── Interceptor2.invoke() ││ │ │ │ ├── 前置逻辑 ││ │ │ │ ├── proceed() ││ │ │ │ │ │ ││ │ │ │ │ ├── 目标方法 ││ │ │ │ │ │ ││ │ │ │ ├── 后置逻辑 ││ │ │ │ └── return ││ │ │ └── return ││ │ └── 后置逻辑 ││ │ └── return ││ └── return ││ │└────────────────────────────────────────────────┘链式追问二:Spring MVC 模式
Section titled “链式追问二:Spring MVC 模式”Q4:Spring MVC 使用了哪些设计模式?高频
Section titled “Q4:Spring MVC 使用了哪些设计模式?”Spring MVC 核心模式:
// 1. 适配器模式:统一不同类型的处理器public interface HandlerAdapter { boolean supports(Object handler); ModelAndView handle(HttpServletRequest req, HttpServletResponse resp, Object handler);}
// 适配 Controller 接口public class SimpleControllerHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { return handler instanceof Controller; }
@Override public ModelAndView handle(HttpServletRequest req, HttpServletResponse resp, Object handler) { return ((Controller) handler).handleRequest(req, resp); }}
// 适配 @RequestMapping 方法public class RequestMappingHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { return handler instanceof HandlerMethod; }
@Override public ModelAndView handle(HttpServletRequest req, HttpServletResponse resp, Object handler) { // 反射调用 @RequestMapping 方法 HandlerMethod handlerMethod = (HandlerMethod) handler; Object returnValue = handlerMethod.getMethod().invoke(handlerMethod.getBean(), args); return handleReturnValue(returnValue); }}
// DispatcherServlet 统一处理public class DispatcherServlet { private List<HandlerAdapter> handlerAdapters;
protected void doDispatch(HttpServletRequest req, HttpServletResponse resp) { Object handler = getHandler(req);
// 找到支持的适配器 HandlerAdapter adapter = getHandlerAdapter(handler);
// 通过适配器统一调用 ModelAndView mv = adapter.handle(req, resp, handler); }}
// 2. 责任链模式:拦截器链public interface HandlerInterceptor { boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler); void postHandle(HttpServletRequest req, HttpServletResponse resp, Object handler, ModelAndView mv); void afterCompletion(HttpServletRequest req, HttpServletResponse resp, Object handler, Exception ex);}
// 拦截器链执行public class HandlerExecutionChain { private final Object handler; private final List<HandlerInterceptor> interceptorList;
public boolean applyPreHandle(HttpServletRequest req, HttpServletResponse resp) { for (int i = 0; i < interceptorList.size(); i++) { HandlerInterceptor interceptor = interceptorList.get(i); if (!interceptor.preHandle(req, resp, handler)) { return false; // 中断链 } } return true; }}
// 3. 观察者模式:事件监听@Componentpublic class AuditListener { @EventListener public void onAuditEvent(AuditEvent event) { // 记录审计日志 }}
// 4. 策略模式:ViewResolverpublic interface ViewResolver { View resolveViewName(String viewName, Locale locale);}
// 不同视图解析策略public class InternalResourceViewResolver implements ViewResolver { }public class ThymeleafViewResolver implements ViewResolver { }public class FreeMarkerViewResolver implements ViewResolver { }Spring MVC 模式架构:
┌────────────────────────────────────────────────┐│ Spring MVC 设计模式应用 │├────────────────────────────────────────────────┤│ ││ DispatcherServlet(前端控制器) ││ │ ││ ├── HandlerMapping(策略模式) ││ │ └── 根据 URL 选择处理器 ││ │ ││ ├── HandlerAdapter(适配器模式) ││ │ ├── Controller 适配器 ││ │ ├── HttpRequestHandler 适配器 ││ │ └── @RequestMapping 适配器 ││ │ ││ ├── HandlerInterceptor(责任链模式) ││ │ └── 拦截器链 ││ │ ││ ├── ViewResolver(策略模式) ││ │ └── 不同视图解析策略 ││ │ ││ └── ApplicationEvent(观察者模式) ││ └── 事件发布和监听 ││ │└────────────────────────────────────────────────┘链式追问三:JDK 中的设计模式
Section titled “链式追问三:JDK 中的设计模式”Q5:JDK 源码中使用了哪些设计模式?高频
Section titled “Q5:JDK 源码中使用了哪些设计模式?”创建型模式:
| 模式 | JDK 应用 | 说明 |
|---|---|---|
| 单例 | Runtime.getRuntime() | 饿汉式单例 |
| 工厂方法 | Calendar.getInstance() | 根据地区返回不同实现 |
| 抽象工厂 | DocumentBuilderFactory | XML 解析器工厂 |
| 建造者 | StringBuilder | 字符串构建 |
| 原型 | Object.clone() | 对象克隆 |
// 1. 单例模式:Runtimepublic class Runtime { private static Runtime currentRuntime = new Runtime(); // 饿汉式
public static Runtime getRuntime() { return currentRuntime; }
private Runtime() {}}
// 2. 工厂方法:Calendarpublic abstract class Calendar { public static Calendar getInstance() { return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT)); }
private static Calendar createCalendar(TimeZone zone, Locale aLocale) { // 根据地区返回不同实现 if (aLocale.equals("th_TH")) { return new BuddhistCalendar(zone, aLocale); } return new GregorianCalendar(zone, aLocale); }}
// 3. 抽象工厂:XML 解析DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document doc = builder.parse("file.xml");结构型模式:
| 模式 | JDK 应用 | 说明 |
|---|---|---|
| 代理 | java.lang.reflect.Proxy | 动态代理 |
| 装饰器 | Java IO 流 | 动态增强 |
| 适配器 | Arrays.asList() | 数组转 List |
| 外观 | javax.faces.context.FacesContext | 统一入口 |
| 组合 | java.awt.Component | 组件树 |
| 享元 | Integer.valueOf() | 缓存 |
// 1. 代理模式:JDK 动态代理UserService proxy = (UserService) Proxy.newProxyInstance( UserService.class.getClassLoader(), new Class[]{UserService.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理拦截"); return method.invoke(target, args); } });
// 2. 装饰器模式:Java IO 流InputStream is = new BufferedInputStream( // 装饰器1:缓冲 new GZIPInputStream( // 装饰器2:解压 new FileInputStream("file.gz") // 被装饰对象 ) );
// 3. 适配器模式:Arrays.asList()String[] array = {"a", "b", "c"};List<String> list = Arrays.asList(array); // 数组适配为 List
// 4. 享元模式:Integer 缓存Integer a = Integer.valueOf(100); // 从缓存获取Integer b = Integer.valueOf(100);System.out.println(a == b); // true行为型模式:
| 模式 | JDK 应用 | 说明 |
|---|---|---|
| 策略 | Comparator | 排序策略 |
| 模板方法 | AbstractList | 定义算法骨架 |
| 观察者 | Observable、EventListener | 事件监听 |
| 迭代器 | Iterator | 遍历集合 |
| 命令 | Runnable | 封装行为 |
| 责任链 | ClassLoader | 双亲委派 |
// 1. 策略模式:ComparatorList<User> users = new ArrayList<>();users.sort((u1, u2) -> u1.getAge() - u2.getAge()); // 年龄排序策略users.sort((u1, u2) -> u1.getName().compareTo(u2.getName())); // 姓名排序策略
// 2. 模板方法模式:AbstractListpublic abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { // 模板方法:定义算法骨架 public int indexOf(Object o) { ListIterator<E> it = listIterator(); // 抽象方法,子类实现 while (it.hasNext()) { if (o.equals(it.next())) { return it.previousIndex(); } } return -1; }
public abstract E get(int index); // 子类实现}
// 3. 命令模式:RunnableThread thread = new Thread(new Runnable() { // 封装任务为对象 @Override public void run() { System.out.println("执行任务"); }});thread.start();
// 4. 责任链模式:ClassLoaderpublic abstract class ClassLoader { protected Class<?> loadClass(String name, boolean resolve) { // 1. 检查是否已加载 Class<?> c = findLoadedClass(name);
if (c == null) { try { // 2. 委派给父加载器(责任链) if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // 父加载器无法加载 }
// 3. 父加载器无法加载,自己加载 if (c == null) { c = findClass(name); } } return c; }}ClassLoader 责任链:
┌────────────────────────────────────────────────┐│ ClassLoader 双亲委派模型 │├────────────────────────────────────────────────┤│ ││ Application ClassLoader ││ │ ││ ├── loadClass("java.lang.String") ││ │ │ ││ │ ├── 委派给父加载器 ││ │ │ ││ │ ▼ ││ │ Extension ClassLoader ││ │ │ ││ │ ├── 委派给父加载器 ││ │ │ ││ │ ▼ ││ │ Bootstrap ClassLoader ││ │ │ ││ │ └── 找到!返回 java.lang.String ││ │ ││ └── 返回 Class 对象 ││ ││ 责任链模式:每个加载器先委派给父加载器 ││ │└────────────────────────────────────────────────┘链式追问四:模板方法模式
Section titled “链式追问四:模板方法模式”Q6:Spring 中哪些地方用到了模板方法模式?高频
Section titled “Q6:Spring 中哪些地方用到了模板方法模式?”定义:在抽象类中定义算法骨架,将某些步骤延迟到子类实现。
Spring 的模板方法应用:
// 1. JdbcTemplate:封装 JDBC 样板代码public class JdbcTemplate { // 模板方法:定义算法骨架 public <T> T query(String sql, RowMapper<T> rowMapper, Object... args) { // 1. 获取连接(固定步骤) Connection con = DataSourceUtils.getConnection(getDataSource());
try { // 2. 创建 Statement(固定步骤) PreparedStatement ps = con.prepareStatement(sql);
// 3. 设置参数(固定步骤) setParameters(ps, args);
// 4. 执行查询(固定步骤) ResultSet rs = ps.executeQuery();
// 5. 映射结果(变化点,由 RowMapper 实现) T result = rowMapper.mapRow(rs, rowNum);
// 6. 关闭资源(固定步骤) JdbcUtils.closeResultSet(rs); JdbcUtils.closeStatement(ps);
return result; } finally { // 7. 释放连接(固定步骤) DataSourceUtils.releaseConnection(con, getDataSource()); } }}
// 使用:只需提供变化的部分jdbcTemplate.query( "SELECT * FROM user WHERE id = ?", (rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name")), // 变化点 1L);
// 2. AbstractApplicationContext:容器刷新流程public abstract class AbstractApplicationContext { // 模板方法:定义容器启动流程(final 防止子类覆盖) public void refresh() { // 1. 准备工作 prepareRefresh();
// 2. 获取 BeanFactory(子类实现) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备 BeanFactory prepareBeanFactory(beanFactory);
try { // 4. 后置处理 BeanFactory(子类扩展点) postProcessBeanFactory(beanFactory);
// 5. 执行 BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源 initMessageSource();
// 8. 初始化事件派发器 initApplicationEventMulticaster();
// 9. 初始化其他特殊 Bean(子类扩展点) onRefresh();
// 10. 注册监听器 registerListeners();
// 11. 初始化所有单例 Bean finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新(子类扩展点) finishRefresh(); } catch (BeansException ex) { destroyBeans(); cancelRefresh(ex); throw ex; } }
// 钩子方法:子类可以覆盖 protected void onRefresh() { } protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }}
// 3. HttpServlet:HTTP 请求处理public abstract class HttpServlet extends GenericServlet { // 模板方法:根据请求方法分发 protected void service(HttpServletRequest req, HttpServletResponse resp) { String method = req.getMethod();
if (method.equals("GET")) { doGet(req, resp); // 子类实现 } else if (method.equals("POST")) { doPost(req, resp); // 子类实现 } else if (method.equals("PUT")) { doPut(req, resp); // 子类实现 } // ... }
// 钩子方法:子类可以覆盖 protected void doGet(HttpServletRequest req, HttpServletResponse resp) { resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); }
protected void doPost(HttpServletRequest req, HttpServletResponse resp) { resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); }}模板方法 vs 策略模式:
| 对比维度 | 模板方法模式 | 策略模式 |
|---|---|---|
| 实现方式 | 继承 | 组合 |
| 变化点 | 钩子方法 | 整个算法 |
| 灵活性 | 较低(继承限制) | 较高(可运行时切换) |
| 适用场景 | 算法骨架固定,步骤可变 | 整个算法可替换 |
链式追问五:观察者模式
Section titled “链式追问五:观察者模式”Q7:Spring 的事件机制是如何体现观察者模式的?高频
Section titled “Q7:Spring 的事件机制是如何体现观察者模式的?”观察者模式定义:当对象状态发生变化时,所有依赖它的观察者都会自动收到通知。
Spring 事件机制:
// 1. 定义事件public class OrderCreatedEvent extends ApplicationEvent { private final Order order;
public OrderCreatedEvent(Object source, Order order) { super(source); this.order = order; }
public Order getOrder() { return order; }}
// 2. 发布事件(被观察者)@Servicepublic class OrderService { @Autowired private ApplicationEventPublisher eventPublisher;
public void createOrder(Order order) { // 业务逻辑 orderRepository.save(order);
// 发布事件 eventPublisher.publishEvent(new OrderCreatedEvent(this, order)); }}
// 3. 监听事件(观察者)@Componentpublic class InventoryListener { @Autowired private InventoryService inventoryService;
@EventListener public void onOrderCreated(OrderCreatedEvent event) { // 扣减库存 inventoryService.deduct(event.getOrder()); }}
@Componentpublic class EmailListener { @Autowired private EmailService emailService;
@EventListener @Async // 异步监听 public void onOrderCreated(OrderCreatedEvent event) { // 发送邮件 emailService.sendConfirmation(event.getOrder()); }}
@Componentpublic class SmsListener { @Autowired private SmsService smsService;
@EventListener @Async public void onOrderCreated(OrderCreatedEvent event) { // 发送短信 smsService.sendNotification(event.getOrder()); }}Spring 事件机制架构:
┌────────────────────────────────────────────────┐│ Spring 事件机制架构 │├────────────────────────────────────────────────┤│ ││ ApplicationEventPublisher(被观察者) ││ │ ││ ├── publishEvent(OrderCreatedEvent) ││ │ ││ ▼ ││ ApplicationEventMulticaster(事件派发器) ││ │ ││ ├── multicastEvent() ││ │ │ ││ │ ├── 调用 Listener1 ││ │ │ └── InventoryListener ││ │ │ └── deduct() ││ │ │ ││ │ ├── 调用 Listener2(异步) ││ │ │ └── EmailListener ││ │ │ └── sendEmail() ││ │ │ ││ │ └── 调用 Listener3(异步) ││ │ └── SmsListener ││ │ └── sendSms() ││ │ ││ └── 所有监听器自动收到通知 ││ │└────────────────────────────────────────────────┘Spring 内置事件:
| 事件 | 触发时机 | 用途 |
|---|---|---|
| ContextRefreshedEvent | 容器刷新完成 | 初始化缓存、预热数据 |
| ContextStartedEvent | 容器启动 | 开始定时任务 |
| ContextStoppedEvent | 容器停止 | 暂停定时任务 |
| ContextClosedEvent | 容器关闭 | 释放资源 |
| ApplicationReadyEvent | 应用就绪 | 健康检查 |
观察者模式 vs 消息队列:
| 对比维度 | Spring 事件(观察者) | 消息队列(MQ) |
|---|---|---|
| 通信方式 | 进程内同步/异步 | 跨进程异步 |
| 可靠性 | 低(进程崩溃丢失) | 高(持久化) |
| 解耦程度 | 中(同一应用) | 高(不同应用) |
| 适用场景 | 模块解耦、事件驱动 | 微服务通信、削峰填谷 |
设计模式面试总结
Section titled “设计模式面试总结”常见追问:
-
Q:为什么 Spring 默认用 CGLIB 而不是 JDK 动态代理? A:Spring Boot 2.x 默认用 CGLIB,原因是:1)避免接口依赖;2)避免类型转换问题;3)JDK 8 之后两者性能差距很小。
-
Q:BeanFactory 和 ApplicationContext 的区别? A:ApplicationContext 继承了 BeanFactory,增加了:国际化、事件发布、资源加载、AOP 支持。ApplicationContext 是增强版的 BeanFactory。
-
Q:Spring 如何解决循环依赖? A:通过三级缓存:singletonObjects(完整 Bean)、earlySingletonObjects(早期引用)、singletonFactories(ObjectFactory)。属性注入的循环依赖可以解决,构造器注入的不行。
-
Q:为什么 Integer.valueOf(100) 返回 true,Integer.valueOf(200) 返回 false? A:Integer.valueOf() 使用享元模式,缓存了 -128 ~ 127 的 Integer 对象。100 在缓存范围内返回同一对象,200 超出缓存范围新建对象。