onApplicationEvent調用了2次,3次,多次

onApplicationEvent調用了2次,3次,多次 解決方案

首先,被執行這麼多次,肯定是自己配置的問題,我以spring boot爲例來說

我也遇到了執行三次,排查後發現一個是spring boot的,另外兩個是自己配的,所以才導致三次,理論上可以導致n次的
三個事件源分別爲:

  1. spring boot 自帶的註解形式上下文(解析所有通過開放端口發來的請求)
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@184497d1, started on Sat Oct 12 10:33:03 CST 2019
  1. 開發者自己創建的(僅負責解析 /ui/** 請求)
org.springframework.context.event.ContextRefreshedEvent[source=WebApplicationContext for namespace 'ui-servlet', started on Sat Oct 12 10:34:53 CST 2019, parent: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@184497d1]
  1. 開發者自己創建的(僅負責解析 /api/** 請求)
org.springframework.context.event.ContextRefreshedEvent[source=WebApplicationContext for namespace 'api-servlet', started on Sat Oct 12 10:35:06 CST 2019, parent: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@184497d1]

可以看到第一個是spring boot自身的,另外兩個是 WebApplicationContext 的不同空間,而他們有同樣的父容器(即第一個)


後面兩個怎麼來的?

@Configuration
public class ServletConfig {

    @Bean
    public ServletRegistrationBean dispatcherUI() {
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        applicationContext.scan("com.xxx.*.controller.ui");
        DispatcherServlet dispatcherServlet = new DispatcherServlet(applicationContext);
        ServletRegistrationBean servletRegistration = new ServletRegistrationBean(dispatcherServlet,"/ui/*");
        servletRegistration.setName("ui"); // 起名
        return servletRegistration;
    }


    @Bean
    public ServletRegistrationBean dispatcherApi() {
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        applicationContext.scan("com.xxx.*.controller.api");
        DispatcherServlet dispatcherServlet = new DispatcherServlet(applicationContext);
        ServletRegistrationBean servletRegistration = new ServletRegistrationBean(dispatcherServlet,"/api/*");
        servletRegistration.setName("api"); // 起名
        return servletRegistration;
    }
}

同時驗證了 spring爲它命名是 xxx-servlet,xxx是自己起的。


只想讓它執行一次?

可見onApplicationEvent被調用多次並不是spring的bug,而是spring爲開發者留的口子,即允許開發者自由自在的關心哪個,執行哪個即可,如果你不說,我就每次都通知你。

一般來說如果作爲啓動配置,不是特定容器的配置的話,只關心spring boot本身那個就好了,判斷一下parent 是否爲空即可。若爲空則證明是root applicationContext。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章