SSM整合时监听器ContextLoaderListener和IntrospectorCleanupListener
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
ContextLoaderListener
ContextLoaderListener作用
ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
ContextLoaderListener文档说明
第一段说明ContextLoader可以由 ContextLoaderListener和ContextLoaderServlet生成。如果查看ContextLoaderServlet的API,可以看到它也关联了ContextLoader这个类而且它实现了HttpServlet这个接口。
第二段,ContextLoader创建的是 XmlWebApplicationContext这样一个类,它实现的接口是WebApplicationContext->ConfigurableWebApplicationContext->ApplicationContext->BeanFactory这样一来spring中的所有bean都由这个类来创建
ContextLoaderListener配置
在web.xml中加入代码:
<!-- 添加ContextLoaderListener监听器相关代码 -->
<listener>
<!-- ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。 -->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
IntrospectorCleanupListener
IntrospectorCleanupListener作用
IntrospectorCleanupListener实现了ServletContextListener接口,也就是说,
在web容器初始化(准确的说是在filters或servlets初始化之前)的时候会执行contextInitialized方法,
在ServletContext销毁(准确的说是在filters和servlets销毁之后)的时候会执行contextDestroyed方法。
销毁ServletContext的时候调用了Introspector.flushCaches方法,清空对应缓存.
注意:在使用Spring本身的时候并不需要使用此监听器,因为Spring自己的内部机制会立即清空对应的缓存。
虽然,Spring本身不存在这样的问题,但是如果和其它框架结合使用,而其它框架有这个问题,如Struts、Quartz等,
那就需要配置这个监听器,在销毁ServletContext的时候清空对应缓存。
IntrospectorCleanupListener文档说明
通过查看Introspector.getBeanInfo方法的源码会发现,Introspector在构建一个BeanInfo对象的时候,会将构建的BeanInfo对象和原类缓存到一个Map中,源码如下。
通过上的代码可以得出,Introspector间接持有了BeanInfo的强引用。如果使用Introspector操作了很多类,那么Introspector将间接持有这些BeanInfo的强引用。在发生垃圾收集的时候,检测到这些BeanInfo存在引用链,则这些类和对应的类加载器将不会被垃圾收集器回收,进而导致内存泄漏。所以,为了解决这个问题,在使用Introspector操作完成后,调用Introspector类的flushCaches方法清除缓存。
通过上面的代码会发现,清除的时候是清空了整个缓存,因为没有很好的办法来确定每个缓存是属于哪个应用的,所以清除的时候会清除所有应用的缓存。
IntrospectorCleanupListener配置
在web.xml中加入代码:
<!-- 添加ContextLoaderListener监听器相关代码 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
说明
IntrospectorCleanupListener在使用时会配合ContextLoaderListener,一般会把web.xml中将IntrospectorCleanupListener配置成非第一个listener。
其实,看过源码的都知道,官方的表述是必须将此监听器配置成web.xml中的第一个listener,才能在合适的时间发挥最有效的作用。
原因其实很简单,在Servlet3.0规范之前,监听器的调用是随机的,而从Servlet3.0开始,监听器的调用顺序是根据其在web.xml中配置的顺序,并且实现ServletContextListener的监听器,contextInitialized方法调用顺序是按照在web.xml中配置的顺序正序依次执行,而contextDestroyed方法的调用顺序是按照在web.xml中配置的顺序逆序依次执行。所以,如果IntrospectorCleanupListener被配置成了第一个listener,那么它的contextDestroyed方法将最后一个执行,将发挥最有效的清除作用;而如果不是,那么可能会残留未被清除的缓存。
本文章借鉴JavaQ,借鉴文章链接:https://www.jianshu.com/p/b167716f9c0c