ApplicationListener因父容器不爲空被屢次執行

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class ParamsContextAdapter implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        try {
            // 生成了兩個AnnotationConfigApplicationContext子容器;
            //父容器爲AnnotationConfigEmbeddedWebApplicationContext;
            //祖父容器爲AnnotationConfigApplicationContext
            ApplicationContext child = event.getApplicationContext();
            ApplicationContext parent = event.getApplicationContext().getParent();
            ApplicationContext grandParent = parent != null ? parent.getParent() : null;
            log.info("當前:{}; 父親:{}; 祖父:{}", child.getDisplayName(), parent == null ? null : parent.getDisplayName(),
                    grandParent == null ? null : grandParent.getDisplayName());

            if (event.getApplicationContext().getParent().getParent() == null) {
                log.info("初始化適配器開始");
                System.out.println("test ApplicationListener");
                log.info("初始化適配器完成");

            }
        } catch (Exception e) {
            log.error("初始化適配器異常", e);
        }

    }
}
  1. 肯定ApplicationListener是針對哪一種特定ApplicationEvent進行監聽
  2. 同時集成了spring和springMVC的話,上下文中會存在父、子容器,(spring配置文件的<context-param>contextConfigLocation的父容器和springMVC配置文件的<init-param>contextConfigLocation的子容器), 在經過applicationContext發送通知的時候,事件可能會被兩個容器同時發佈。能夠先排除是否因爲配置有誤形成。再給定執行前的斷定java

    @Override  
    public void onApplicationEvent(ContextRefreshedEvent event) {  
        if(event.getApplicationContext().getParent() == null){  
             //須要執行的邏輯代碼,當spring容器初始化完成後就會執行該方法。  
        }  
    }

源碼解析

在AbstractApplicationContext.refresh(); 對容器加載編排的過程當中,若是父容器不爲空,父容器也publish事件源,因此生成了幾回容器也對執行有影響spring

AbstractApplicationContext:

	protected void finishRefresh() {
		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event. 將上下文ApplicationContext注入到ContextRefreshedEvent中
		publishEvent(new ContextRefreshedEvent(this));
	}

	public void publishEvent(ApplicationEvent event) {
		Assert.notNull(event, "Event must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Publishing event in " + getDisplayName() + ": " + event);
		}
		getApplicationEventMulticaster().multicastEvent(event);
		if (this.parent != null) {
			this.parent.publishEvent(event); // 若是父容器不爲空,父容器也publish事件源
		}
	}
相關文章
相關標籤/搜索