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

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

首先,被執行這麼屢次,確定是本身配置的問題,我以spring boot爲例來講java

我也遇到了執行三次,排查後發現一個是spring boot的,另外兩個是本身配的,因此才致使三次,理論上能夠致使n次的
三個事件源分別爲:web

  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 的不一樣空間,而他們有一樣的父容器(即第一個)spring


後面兩個怎麼來的?

@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是本身起的。api


只想讓它執行一次?

可見onApplicationEvent被調用屢次並非spring的bug,而是spring爲開發者留的口子,即容許開發者自由自在的關心哪一個,執行哪一個便可,若是你不說,我就每次都通知你。app

通常來講若是做爲啓動配置,不是特定容器的配置的話,只關心spring boot自己那個就行了,判斷一下parent 是否爲空便可。若爲空則證實是root applicationContext。svg