Spring中事件监听(通知)机制详解与实践

简介: Spring中事件监听(通知)机制详解与实践

Spring中事件监听(也有说法叫事件通知)机制,其实本质是观察者模式的应用。当某个事件发生时,其会被广播出去,监听该实践的listener就会被触发然后执行响应的动作。该模式可良好应用于程序解耦,类似消息的发布订阅。


【1】事件、发布与监听

这个模式有三元素:事件、发布与监听。


① 事件

如下图所示,事件继承自EventObject类,该类维护了事件最初发生在其上的对象-source。而我们通常自定义的事件实际应继承自抽象类ApplicationEvent。比如常见的上下文刷新事件ContextRefreshedEvent



比如我们可以自定义事件类如下:

// 定义一个事件
public class MyEvent extends ApplicationEvent {
    private String message;
    public EventDemo(Object source, String message) {
        super(source);
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
}


② 监听

有了事件后,就需要有对应的监听对象–其实就是观察者。接口EventListener是一个顶级接口提供给其他监听器接口继承,如下所示其是一个空接口。

public interface EventListener {
}


针对ApplicationEvent事件而言,Spring提供了ApplicationListener功能接口供用户实现,如下所示:

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
   // 处理监听到的事件
  void onApplicationEvent(E event);
  static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {
    return event -> consumer.accept(event.getPayload());
  }
}


么我们自定义监听该如何实现呢?有两种方式:继承自ApplicationListener或者使用注解@EventListener

如下所示继承ApplicationListener:

// 定义一个事件监听者
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        // 这里写事件处理逻辑
    }
}


如下所示使用注解@EventListener

// 定义一个事件监听者
@Component
public class MyEventListener  {
    @EventListener
    public void onApplicationEvent(MyEvent event) {
        // 这里写事件处理逻辑
    }
}


使用注解 @EventListener该种方式将会被包装为一个ApplicationListenerMethodAdapter,类似如下:


这是因为EventListenerMethodProcessor 处理器会解析@EventListener 注解,将其所在类封装为一个ApplicationListener(比如这里的ApplicationListenerMethodAdapter),然后放入容器中。EventListenerMethodProcessor实现了SmartInitializingSingleton、ApplicationContextAware以及BeanFactoryPostProcessorj接口,有兴趣的可以看下其源码。常见的ApplicationListener树结构示意图

③ 事件发布

有了事件与监听 ,那么还需要在某个时刻将事件广播出去触发监听动作。如何发布事件呢?Spring提供了ApplicationEventPublisher接口。

@FunctionalInterface
public interface ApplicationEventPublisher {
  default void publishEvent(ApplicationEvent event) {
    publishEvent((Object) event);
  }
  void publishEvent(Object event);
}


publishEvent方法解释如下:


将此事件通知给所有注册到容器的并且匹配的监听器,事件可以是框架事件(例如ContextRefreshedEvent)或特定于应用程序的事件。

这样的事件发布步骤实际是一种对于multicaster 的协调手段,其并不意味着同步、异步或者立即执行。

对于那些需要长时间处理或者可能阻塞的操作,事件监听器被鼓励使用异步处理

该接口不需要我们去实现,实际上如下图所示所有的容器都实现了该接口:


ccf93669f7e74f1ca51b3e6c36e104fe.png

那么我们该如何做呢?只需要注入ApplicationEventPublisher 然后发布即可,如下所示:

@Autowired
ApplicationEventPublisher applicationEventPublisher;
public void publishEvent(){
    MyEvent event = new MyEvent(this);
    applicationEventPublisher.publishEvent(event);
}


如何使用异步处理呢?使用@EnableAsync与@Async注解。

【2】事件广播

publishEvent方法会将我们的事件通知给监听器,这个场景叫做广播。也就是说,将该事件广播出去,但凡对该事件感兴趣的监听器均被通知到。spring是如何实现的呢?


① publishEvent

这个逻辑是在AbstractApplicationContext的publishEvent中实现的。 也就是说AbstractApplicationContext实现了ApplicationEventPublisher 接口的publishEvent方法哦。

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
  Assert.notNull(event, "Event must not be null");
  // Decorate event as an ApplicationEvent if necessary
  ApplicationEvent applicationEvent;
  if (event instanceof ApplicationEvent) {
    applicationEvent = (ApplicationEvent) event;
  }
  else {
    applicationEvent = new PayloadApplicationEvent<>(this, event);
    if (eventType == null) {
      eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
    }
  }
  // Multicast right now if possible - or lazily once the multicaster is initialized
  //如果早期事件不为null,则将事件放入早期事件集合中--说明广播器还没有实例化好
  if (this.earlyApplicationEvents != null) {
    this.earlyApplicationEvents.add(applicationEvent);
  }
  else {
  // 获取广播器进行事件广播
    getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
  }
  // Publish event via parent context as well...
  //将事件也交给父类处理
  if (this.parent != null) {
    if (this.parent instanceof AbstractApplicationContext) {
      ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
    }
    else {
      this.parent.publishEvent(event);
    }
  }
}

上述方法首先对event进行了处理,尝试转换为ApplicationEvent或者PayloadApplicationEvent,如果是PayloadApplicationEvent则获取eventType。


其次判断earlyApplicationEvents是否为空(也就是早期事件还没有被发布-说明广播器还没有实例化好),如果不为空则将当前事件放入否则获取ApplicationEventMulticaster调用其multicastEvent将事件广播出去。本文这里获取到的广播器实例是SimpleApplicationEventMulticaster。


最后如果其parent不为null,则尝试调用父类的publishEvent方法。

② multicastEvent

我们继续看下multicastEvent方法的实现。这里我们来到了SimpleApplicationEventMulticastermulticastEven方法。

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 解析事件类型
  ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
  // 尝试获取任务执行器
  Executor executor = getTaskExecutor();
  // 获取合适的ApplicationListener,循环调用监听器的onApplicationEvent方法
  for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    // 判断executor 是否不为null
    if (executor != null) {
      executor.execute(() -> invokeListener(listener, event));
    }
    // 判断applicationStartup 
    else if (this.applicationStartup != null) {
      StartupStep invocationStep = this.applicationStartup.start("spring.event.invoke-listener");
      invokeListener(listener, event);
      invocationStep.tag("event", event::toString);
      if (eventType != null) {
        invocationStep.tag("eventType", eventType::toString);
      }
      invocationStep.tag("listener", listener::toString);
      invocationStep.end();
    }
    // 否则,直接调用listener.onApplicationEvent
    else {
      invokeListener(listener, event);
    }
  }
}


代码逻辑分析如下:

① 获取事件类型与TaskExecutor;

② getApplicationListeners获取合适的监听器,也就是对当前事件类型感兴趣的;然后进行遍历

③ 如果executor不为null,则交给executor去调用监听器;

④ 如果applicationStartup不为null,则会额外记录处理步骤;

⑤ 否则,使用当前主线程直接调用监听器;

getApplicationListeners如何获取合适的监听器?如果监听器是GenericApplicationListener则触发其supportsEventType和supportsSourceType方法,否则使用GenericApplicationListenerAdapter包装然后判断其 是SmartApplicationListener则根据其supportsEventType方法判断,否则根据监听器实现的接口泛型来判断。

// AbstractApplicationEventMulticaster
protected boolean supportsEvent(
    ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
  GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
      (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
  return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
// GenericApplicationListenerAdapter
public boolean supportsEventType(ResolvableType eventType) {
  if (this.delegate instanceof SmartApplicationListener) {
    Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
    return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
  }
  else {
    return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
  }
}

③ invokeListener

invokeListener做了什么呢?我们继续往下看。

// 该方法增加了错误处理逻辑,然后调用doInvokeListener
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
  ErrorHandler errorHandler = getErrorHandler();
  if (errorHandler != null) {
    try {
      doInvokeListener(listener, event);
    }
    catch (Throwable err) {
      errorHandler.handleError(err);
    }
  }
  else {
    doInvokeListener(listener, event);
  }
}
// doInvokeListener 直接调用listener.onApplicationEvent
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
  try {
    listener.onApplicationEvent(event);
  }
  catch (ClassCastException ex) {
  //...
  }
}


两个方法流程逻辑很清晰,关键的问题是listener.onApplicationEvent(event);是直接调用你的监听器方法吗?非也,要看此时的listener是什么。比如当你使用注解@EventListener声明监听器的时候,这里的listener就是ApplicationListenerMethodAdapter实例。


以ApplicationListenerMethodAdapter为例,其onApplicationEvent方法会调用processEvent方法最终调用Object result = doInvoke(args);而doInvoke最终是反射调用你的监听器(方法)。

@Override
public void onApplicationEvent(ApplicationEvent event) {
  processEvent(event);
}
public void processEvent(ApplicationEvent event) {
  Object[] args = resolveArguments(event);
  if (shouldHandle(event, args)) {
    Object result = doInvoke(args);
    if (result != null) {
      handleResult(result);
    }
    else {
      logger.trace("No result object given - no result to handle");
    }
  }
}
@Nullable
protected Object doInvoke(Object... args) {
// 获取包装的bean,也就是目标bean,也就是你的监听器
  Object bean = getTargetBean();
  // Detect package-protected NullBean instance through equals(null) check
  if (bean.equals(null)) {
    return null;
  }
  // 设置方法可以访问
  ReflectionUtils.makeAccessible(this.method);
  try {
  // 反射调用目标方法
    return this.method.invoke(bean, args);
  }
  //...一堆catch
}

【3】广播器ApplicationEventMulticaster

这里我们主要分析ApplicationEventMulticaster接口、抽象类


AbstractApplicationEventMulticaster以及具体实现SimpleApplicationEventMulticaster

① ApplicationEventMulticaster

该接口实现将会管理一系列ApplicationListener并发布事件给监听器。

我们看下该接口源码,如下所示该接口提供了添加/移除监听器以及广播事件给监听器的行为。

public interface ApplicationEventMulticaster {
   // 添加监听器
  void addApplicationListener(ApplicationListener<?> listener);
   // 添加一个监听器 beanName
  void addApplicationListenerBean(String listenerBeanName);
   // 从通知列表移除掉一个监听器
  void removeApplicationListener(ApplicationListener<?> listener);
   // 从通知列表移除掉一个 监听器 bean name
  void removeApplicationListenerBean(String listenerBeanName);
   // 移除掉该广播器管理的所有监听器
  void removeAllListeners();
  /**
   * Multicast the given application event to appropriate listeners.
   * <p>Consider using {@link #multicastEvent(ApplicationEvent, ResolvableType)}
   * if possible as it provides better support for generics-based events.
   * @param event the event to multicast
   */
   // 广播事件给合适的监听器 建议使用末尾方法其对泛型提供了更好支持
  void multicastEvent(ApplicationEvent event);
// 广播事件给合适的监听器,如果eventType为null,将会根据event 实例构建一个默认的type
  void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}


② AbstractApplicationEventMulticaster

该抽象类实现了ApplicationEventMulticaster接口,提供了基础的监听器注册/移除以及查找能力。


其中defaultRetriever 用来管理监听器并进行查找,而retrieverCache 则是为了更快进行查找。

private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();
final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);

如下是其方法示意图:


其内部类DefaultListenerRetriever维护了两个常量集合用来保存监听器与监听器 bean Name。Set表示集合内部元素不可重复。

public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
public final Set<String> applicationListenerBeans = new LinkedHashSet<>();


抽象类并未提供广播事件的功能,留给子类SimpleApplicationEventMulticaster实现。

③ SimpleApplicationEventMulticaster


默认情况下,该广播器将会把事件广播给所有的监听器,让监听器自己忽略他们不感兴趣的事件。默认情况下,所有监听器将会在当前线程中会调用。这允许恶意侦听器阻塞整个应用程序的危险,但会增加最小的开销。指定额外的任务执行器TaskExecutor,使监听器在不同线程中执行,例如从线程池执行,将是一个良好的方案。setTaskExecutor方法允许你实例化SimpleApplicationEventMulticaster时,指定额外的任务执行器。这样监听器将不会在当前被调用的线程中执行。

public void setTaskExecutor(@Nullable Executor taskExecutor) {
  this.taskExecutor = taskExecutor;
}

Spring提供了两个任务执行器供你使用:

  • 同步执行器 org.springframework.core.task.SyncTaskExecutor
  • 异步执行器 org.springframework.core.task.SimpleAsyncTaskExecutor

核心属性

// 任务执行器,可以使监听器不在主线程中执行
@Nullable
private Executor taskExecutor;
// 错误处理器
@Nullable
private ErrorHandler errorHandler;
// 应用启动记录
@Nullable
private ApplicationStartup applicationStartup;

ApplicationStartup 这个玩意很有一起,主要是用来标记/记录程序处理步骤。核心容器及其基础结构组件可以使用ApplicationStartup 标记应用程序启动期间的步骤,并收集有关执行上下文或其处理时间的数据。


事件广播

这个其实在上面我们已经分析过了,这里可以再看下源码。简单来说该方法就是解析事件类型、尝试获取任务执行器,然后调用父类的getApplicationListeners方法获取监听器进行遍历循环调用invokeListener(listener, event);

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
  ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
  Executor executor = getTaskExecutor();
  for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    if (executor != null) {
      executor.execute(() -> invokeListener(listener, event));
    }
    else if (this.applicationStartup != null) {
      StartupStep invocationStep = this.applicationStartup.start("spring.event.invoke-listener");
      invokeListener(listener, event);
      invocationStep.tag("event", event::toString);
      if (eventType != null) {
        invocationStep.tag("eventType", eventType::toString);
      }
      invocationStep.tag("listener", listener::toString);
      invocationStep.end();
    }
    else {
      invokeListener(listener, event);
    }
  }
}

【4】广播器与监听器的注册

其实这里要说的是什么时候广播器被初始化?什么时候监听器被注册到了容器。这个发生在spring容器的初始化过程中,确切地说是SpringMVC容器还是IOC容器要看你当前项目环境是什么。这里我们重点不在于这里,我们看如下AbstractApplicationContext.refresh方法。

@Override
public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
    StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    // Prepare this context for refreshing.
    prepareRefresh();
    // Tell the subclass to refresh the internal bean factory.
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    // Prepare the bean factory for use in this context.
    prepareBeanFactory(beanFactory);
    try {
      // Allows post-processing of the bean factory in context subclasses.
      postProcessBeanFactory(beanFactory);
      StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
      // Invoke factory processors registered as beans in the context.
      invokeBeanFactoryPostProcessors(beanFactory);
      // Register bean processors that intercept bean creation.
      registerBeanPostProcessors(beanFactory);
      beanPostProcess.end();
      // Initialize message source for this context.
      initMessageSource();
      // Initialize event multicaster for this context.
      initApplicationEventMulticaster();
      // Initialize other special beans in specific context subclasses.
      onRefresh();
      // Check for listener beans and register them.
      registerListeners();
      // Instantiate all remaining (non-lazy-init) singletons.
      finishBeanFactoryInitialization(beanFactory);
      // Last step: publish corresponding event.
      finishRefresh();
    }
    catch (BeansException ex) {
      if (logger.isWarnEnabled()) {
        logger.warn("Exception encountered during context initialization - " +
            "cancelling refresh attempt: " + ex);
      }
      // Destroy already created singletons to avoid dangling resources.
      destroyBeans();
      // Reset 'active' flag.
      cancelRefresh(ex);
      // Propagate exception to caller.
      throw ex;
    }
    finally {
      // Reset common introspection caches in Spring's core, since we
      // might not ever need metadata for singleton beans anymore...
      resetCommonCaches();
      contextRefresh.end();
    }
  }
}

这里我们主要看initApplicationEventMulticasterregisterListeners();方法。前者就是初始化事件广播器,后置则是注册监听。

① initApplicationEventMulticaster

源码如下所示,如果beanFactory有bean applicationEventMulticaster则获取该bean实例。否则就实例化一个SimpleApplicationEventMulticaster 实例作为applicationEventMulticaster 并调用beanFactory.registerSingleton注册。

public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME 
= "applicationEventMulticaster";
protected void initApplicationEventMulticaster() {
  ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
    this.applicationEventMulticaster =
        beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    if (logger.isTraceEnabled()) {
      logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
    }
  }
  else {
    SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
    simpleApplicationEventMulticaster.setApplicationStartup(getApplicationStartup());
    this.applicationEventMulticaster = simpleApplicationEventMulticaster;
    // 将事件广播器作为单例bean注册到BeanFactory中
    beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    if (logger.isTraceEnabled()) {
      logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
          "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
    }
  }
}

② registerListeners

实例化完事件广播器后,触发了registerListeners。这里会搜集ApplicationListener交给广播器实例。

protected void registerListeners() {
  // Register statically specified listeners first.
  for (ApplicationListener<?> listener : getApplicationListeners()) {
    getApplicationEventMulticaster().addApplicationListener(listener);
  }
  // Do not initialize FactoryBeans here: We need to leave all regular beans
  // uninitialized to let post-processors apply to them!
  String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
  for (String listenerBeanName : listenerBeanNames) {
    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
  }
  // Publish early application events now that we finally have a multicaster...
  Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
  // 这里将earlyApplicationEvents 置为了null!
  this.earlyApplicationEvents = null;
  if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
    for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
      getApplicationEventMulticaster().multicastEvent(earlyEvent);
    }
  }
}


方法逻辑主要分为三块:


① getApplicationListeners获取监听器然后注册到广播器中;

② getBeanNamesForType获取bean Name数组String[] listenerBeanNames 然后注册到广播器中;

③ 处理以前的事件,先将earlyApplicationEvents 赋予null,然后判断earlyEventsToProcess 如果不为空就广播出去

目录
相关文章
|
4月前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段四:学术分析 AI 项目 RAG 落地指南:基于 Spring AI 的本地与阿里云知识库实践
本文介绍RAG(检索增强生成)技术,结合Spring AI与本地及云知识库实现学术分析AI应用,利用阿里云Qwen-Plus模型提升回答准确性与可信度。
1527 90
AI 超级智能体全栈项目阶段四:学术分析 AI 项目 RAG 落地指南:基于 Spring AI 的本地与阿里云知识库实践
|
6月前
|
前端开发 Java API
利用 Spring WebFlux 技术打造高效非阻塞 API 的完整开发方案与实践技巧
本文介绍了如何使用Spring WebFlux构建高效、可扩展的非阻塞API,涵盖响应式编程核心概念、技术方案设计及具体实现示例,适用于高并发场景下的API开发。
513 0
|
8月前
|
人工智能 JSON 安全
Spring Boot实现无感刷新Token机制
本文深入解析在Spring Boot项目中实现JWT无感刷新Token的机制,涵盖双Token策略、Refresh Token安全性及具体示例代码,帮助开发者提升用户体验与系统安全性。
906 4
|
4月前
|
人工智能 监控 Java
Spring AI Alibaba实践|后台定时Agent
基于Spring AI Alibaba框架,可构建自主运行的AI Agent,突破传统Chat模式限制,支持定时任务、事件响应与人工协同,实现数据采集、分析到决策的自动化闭环,提升企业智能化效率。
Spring AI Alibaba实践|后台定时Agent
|
6月前
|
Java 应用服务中间件 开发者
Spring Boot 技术详解与应用实践
本文档旨在全面介绍 Spring Boot 这一广泛应用于现代企业级应用开发的框架。内容将涵盖 Spring Boot 的核心概念、核心特性、项目自动生成与结构解析、基础功能实现(如 RESTful API、数据访问)、配置管理以及最终的构建与部署。通过本文档,读者将能够理解 Spring Boot 如何简化 Spring 应用的初始搭建和开发过程,并掌握其基本使用方法。
486 2
|
10月前
|
JSON 前端开发 Java
深入理解 Spring Boot 中日期时间格式化:@DateTimeFormat 与 @JsonFormat 完整实践
在 Spring Boot 开发中,日期时间格式化是前后端交互的常见痛点。本文详细解析了 **@DateTimeFormat** 和 **@JsonFormat** 两个注解的用法,分别用于将前端传入的字符串解析为 Java 时间对象,以及将时间对象序列化为指定格式返回给前端。通过完整示例代码,展示了从数据接收、业务处理到结果返回的全流程,并总结了解决时区问题和全局配置的最佳实践,助你高效处理日期时间需求。
1428 0
|
10月前
|
存储 Java 数据库
Spring Boot 注册登录系统:问题总结与优化实践
在Spring Boot开发中,注册登录模块常面临数据库设计、密码加密、权限配置及用户体验等问题。本文以便利店销售系统为例,详细解析四大类问题:数据库字段约束(如默认值缺失)、密码加密(明文存储风险)、Spring Security配置(路径权限不当)以及表单交互(数据丢失与提示不足)。通过优化数据库结构、引入BCrypt加密、完善安全配置和改进用户交互,提供了一套全面的解决方案,助力开发者构建更 robust 的系统。
344 0
|
7月前
|
JSON 前端开发 Java
Spring MVC 核心组件与请求处理机制详解
本文解析了 Spring MVC 的核心组件及请求流程,核心组件包括 DispatcherServlet(中央调度)、HandlerMapping(URL 匹配处理器)、HandlerAdapter(执行处理器)、Handler(业务方法)、ViewResolver(视图解析),其中仅 Handler 需开发者实现。 详细描述了请求执行的 7 步流程:请求到达 DispatcherServlet 后,经映射器、适配器找到并执行处理器,再通过视图解析器渲染视图(前后端分离下视图解析可省略)。 介绍了拦截器的使用(实现 HandlerInterceptor 接口 + 配置类)及与过滤器的区别
618 0
|
7月前
|
缓存 安全 Java
Spring 框架核心原理与实践解析
本文详解 Spring 框架核心知识,包括 IOC(容器管理对象)与 DI(容器注入依赖),以及通过注解(如 @Service、@Autowired)声明 Bean 和注入依赖的方式。阐述了 Bean 的线程安全(默认单例可能有安全问题,需业务避免共享状态或设为 prototype)、作用域(@Scope 注解,常用 singleton、prototype 等)及完整生命周期(实例化、依赖注入、初始化、销毁等步骤)。 解析了循环依赖的解决机制(三级缓存)、AOP 的概念(公共逻辑抽为切面)、底层动态代理(JDK 与 Cglib 的区别)及项目应用(如日志记录)。介绍了事务的实现(基于 AOP
256 0

热门文章

最新文章