跳转到主内容
极星编程网:以代码为星,赴技术山海!

Web.xml listener配置 监听器Listener的加载顺序

web.xml中按XML从上到下顺序加载,先于Servlet和Filter;同一类重复声明会创建多个实例;web.xml配置优先级高于@WebListener注解。 web.xml 中
的加载顺序由配置顺序决定 容器(如 Tomcat)按
web.xml
中
元素出现的**从上到下顺序**依次实例化并调用
contextInitialized()
。这不是“优先级”或“依赖声明”,就是纯文本顺序。 多个
块,谁写在前面,谁先初始化 同一个类被重复声明两次?会创建两个实例,且按两次出现的位置分别触发 不支持通过属性(如
order
)控制顺序;XML Schema 里没这字段 如果依赖关系复杂(比如 A 要用 B 初始化后的上下文属性),只能靠人工排位置,别指望容器自动拓扑排序 Listener 加载早于 Servlet 和 Filter
是整个 Web 应用生命周期最早介入的扩展点之一——比
的
load-on-startup
、也比所有
都早。这意味着:
ServletContext
已创建,但
ServletConfig
还不存在(因为还没到 Servlet 阶段) 不能在
contextInitialized()
里调用
getServletRegistration()
或访问具体 Servlet 实例 适合做全局资源预热(如连接池初始化、缓存加载)、监听器自身注册(如
ServletContextAttributeListener
) 若在此阶段抛出异常,整个应用启动失败,日志里通常会带
StandardContext.startInternal
和
ListenerStartException
与注解 @WebListener 冲突时,web.xml 优先级更高 当同时存在 XML 配置和
@WebListener
注解时,Servlet 规范明确要求:web.xml 中声明的
**必须先于** 所有注解发现的 Listener 加载。 也就是说,即使你写了
@WebListener(order = 1)
,它也排在所有 XML 里的
后面 混合使用极易导致顺序误判——建议二选一:全 XML 或全注解(推荐后者,更可控) Tomcat 9+ 对注解 Listener 支持稳定,但某些老版本或 WebLogic 等商用容器对
@WebListener
的发现时机可能有偏差 验证方式:在每个 Listener 的
contextInitialized()
里打日志,看输出顺序 常见陷阱:Listener 拿不到 Spring 上下文 很多人想在
ServletContextListener
里直接获取 Spring 的
ApplicationContext
,结果得到
null
——因为 Spring 的
ContextLoaderListener
本身就是一个
,它只是“恰好”常被写在最前面,但不是魔法。 如果你的 Listener 在
ContextLoaderListener
之前定义,
WebApplicationContext
就还没创建 正确做法:确保你的 Listener 在
ContextLoaderListener
之后(XML 中位置靠下),或监听
ContextRefreshedEvent
(需实现
ApplicationListener
) 不要在
contextInitialized()
里硬等 Spring 上下文就绪——没有回调机制,轮询或 sleep 都是反模式 更安全的替代:把初始化逻辑拆进 Spring Bean 的
@PostConstruct
或
InitializingBean.afterPropertiesSet()
实际顺序问题往往卡在“以为容器懂依赖,其实只认行号”。多一个 Listener 就多一分顺序风险,能合并的逻辑尽量收进同一个 Listener 里。

相关文章