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事件源
		}
	}
相关文章
相关标签/搜索