Skip to content

设计模式在 Spring/JDK 中的应用汇总

面试官:你说了解设计模式,那你能说说 Spring 框架里用了哪些设计模式吗?

:Spring 框架大量使用了设计模式,核心的有工厂模式(BeanFactory)、单例模式(Bean 默认 scope)、代理模式(AOP)、模板方法模式(JdbcTemplate)、观察者模式(ApplicationEvent)等。

面试官:能具体说说 BeanFactory 和 FactoryBean 的区别吗?它们各自体现了什么模式?

这道题是设计模式面试的「综合考题」。能流利说出 6-8 个有源码支撑的例子,并区分易混淆的概念,就能让面试官印象深刻。


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 的区别?”

核心区别

对比维度BeanFactoryFactoryBean
定义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);
}
// 实现类:DefaultListableBeanFactory
public 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 整合 Spring
public 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 配置
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean; // 返回 FactoryBean,Spring 会调用 getObject() 获取真正的 Bean
}
// 获取 Bean
SqlSession session = applicationContext.getBean(SqlSession.class); // 获取的是 SqlSession,不是 SqlSessionFactoryBean

FactoryBean 的使用场景

场景示例说明
框架整合SqlSessionFactoryBeanMyBatis 整合 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 │
│ │
└────────────────────────────────────────────────┘

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. 观察者模式:事件监听
@Component
public class AuditListener {
@EventListener
public void onAuditEvent(AuditEvent event) {
// 记录审计日志
}
}
// 4. 策略模式:ViewResolver
public 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(观察者模式) │
│ └── 事件发布和监听 │
│ │
└────────────────────────────────────────────────┘

Q5:JDK 源码中使用了哪些设计模式?高频

Section titled “Q5:JDK 源码中使用了哪些设计模式?”

创建型模式

模式JDK 应用说明
单例Runtime.getRuntime()饿汉式单例
工厂方法Calendar.getInstance()根据地区返回不同实现
抽象工厂DocumentBuilderFactoryXML 解析器工厂
建造者StringBuilder字符串构建
原型Object.clone()对象克隆
// 1. 单例模式:Runtime
public class Runtime {
private static Runtime currentRuntime = new Runtime(); // 饿汉式
public static Runtime getRuntime() {
return currentRuntime;
}
private Runtime() {}
}
// 2. 工厂方法:Calendar
public 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定义算法骨架
观察者ObservableEventListener事件监听
迭代器Iterator遍历集合
命令Runnable封装行为
责任链ClassLoader双亲委派
// 1. 策略模式:Comparator
List<User> users = new ArrayList<>();
users.sort((u1, u2) -> u1.getAge() - u2.getAge()); // 年龄排序策略
users.sort((u1, u2) -> u1.getName().compareTo(u2.getName())); // 姓名排序策略
// 2. 模板方法模式:AbstractList
public 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. 命令模式:Runnable
Thread thread = new Thread(new Runnable() { // 封装任务为对象
@Override
public void run() {
System.out.println("执行任务");
}
});
thread.start();
// 4. 责任链模式:ClassLoader
public 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 对象 │
│ │
│ 责任链模式:每个加载器先委派给父加载器 │
│ │
└────────────────────────────────────────────────┘

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 策略模式

对比维度模板方法模式策略模式
实现方式继承组合
变化点钩子方法整个算法
灵活性较低(继承限制)较高(可运行时切换)
适用场景算法骨架固定,步骤可变整个算法可替换

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. 发布事件(被观察者)
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createOrder(Order order) {
// 业务逻辑
orderRepository.save(order);
// 发布事件
eventPublisher.publishEvent(new OrderCreatedEvent(this, order));
}
}
// 3. 监听事件(观察者)
@Component
public class InventoryListener {
@Autowired
private InventoryService inventoryService;
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 扣减库存
inventoryService.deduct(event.getOrder());
}
}
@Component
public class EmailListener {
@Autowired
private EmailService emailService;
@EventListener
@Async // 异步监听
public void onOrderCreated(OrderCreatedEvent event) {
// 发送邮件
emailService.sendConfirmation(event.getOrder());
}
}
@Component
public 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)
通信方式进程内同步/异步跨进程异步
可靠性低(进程崩溃丢失)高(持久化)
解耦程度中(同一应用)高(不同应用)
适用场景模块解耦、事件驱动微服务通信、削峰填谷

常见追问

  1. Q:为什么 Spring 默认用 CGLIB 而不是 JDK 动态代理? A:Spring Boot 2.x 默认用 CGLIB,原因是:1)避免接口依赖;2)避免类型转换问题;3)JDK 8 之后两者性能差距很小。

  2. Q:BeanFactory 和 ApplicationContext 的区别? A:ApplicationContext 继承了 BeanFactory,增加了:国际化、事件发布、资源加载、AOP 支持。ApplicationContext 是增强版的 BeanFactory。

  3. Q:Spring 如何解决循环依赖? A:通过三级缓存:singletonObjects(完整 Bean)、earlySingletonObjects(早期引用)、singletonFactories(ObjectFactory)。属性注入的循环依赖可以解决,构造器注入的不行。

  4. Q:为什么 Integer.valueOf(100) 返回 true,Integer.valueOf(200) 返回 false? A:Integer.valueOf() 使用享元模式,缓存了 -128 ~ 127 的 Integer 对象。100 在缓存范围内返回同一对象,200 超出缓存范围新建对象。