纵观java的开源框架,strtus,spring或者是springmvc等,他们的启动都有个共同的特点就是在服务器启动的时候预先加载进来相应的信息,初始化相关的类,他们或者用Servlet实现如sturts1和springmvc,或者用监听器和过滤器,总之一切的准备工作都是对容器里所有的类进行加载和调用的管理以及更好的解耦合。下面主要讨论spring启动的三种常见方式。
spring启动可以选中监听器也可以选择过滤器一下要介绍的三种方式是:IntrospectorCleanupListener初始化spring容器,ContextLoadListener启动spring及ContextLoaderServlet
IntrospectorCleanupListener简介
spring中的提供了一个名为org.springframework.web.util.IntrospectorCleanupListener的监听器。它主要负责处理由 JavaBeans Introspector的使用而引起的缓冲泄露。spring中对它的描述如下:
它是一个在web应用关闭的时候,清除JavaBeans Introspector的监听器.在web.xml中注册这个listener.可以保证在web 应用关闭的时候释放与掉这个web 应用相关的class loader 和由它管理的类
如果你使用了JavaBeans Introspector来分析应用中的类,Introspector 缓冲中会保留这些类的引用.结果在你的应用关闭的时候,这些类以及web 应用相关的class loader没有被垃圾回收.
不幸的是,清除Introspector的唯一方式是刷新整个缓冲.这是因为我们没法判断哪些是属于你的应用的引用.所以删除被缓冲的introspection会导致把这台电脑上的所有应用的introspection都删掉.
需要注意的是,spring 托管的bean不需要使用这个监听器.因为spring它自己的introspection所使用的缓冲在分析完一个类之后会被马上从javaBeans Introspector缓冲中清除掉.
应用程序中的类从来不直接使用JavaBeans Introspector.所以他们一般不会导致内部查看资源泄露.但是一些类库和框架往往会产生这个问题.例如:Struts 和Quartz.
单个的内部查看泄漏会导致整个的web应用的类加载器不能进行垃圾回收.在web应用关闭之后,你会看到此应用的所有静态类资源(例如单例).这个错误当然不是由这个类自身引起的.
ContextLoaderListener简介
与BeanFactory通常以编程的方式被创建不同的是,ApplicationContext能以声明的方式创建,如使用ContextLoader。当然你也可以使用ApplicationContext的实现之一来以编程的方式创建ApplicationContext实例。首先,让我们先分析ContextLoader接口及其实现。
ContextLoader接口有两个实现:ContextLoaderListener和ContextLoaderServlet。两者都实现同样的功能,但不同的是,ContextLoaderListener不能在与Servlet 2.2兼容的web容器中使用。根据Servlet 2.4规范, servlet context listener要在web应用程序的servlet context建立后立即执行,并要能够响应第一个请求(在servlet context要关闭时也一样):这样一个servlet context listener是初始化Spring ApplicationContext的理想场所。虽然使用哪个完全取决于你,但是在同等条件下应该首选ContextLoaderListener;对于更多兼容性的信息,请查看ContextLoaderServlet的JavaDoc。
你可以象下面那样使用ContextLoaderListener来注册一个ApplicationContext:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- or use the ContextLoaderServlet instead of the above listener
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
-->
监听器首先检查contextConfigLocation参数,如果它不存在,它将使用/WEB-INF/applicationContext.xml作为默认值。如果已存在,它将使用分隔符(逗号、冒号或空格)将字符串分解成应用上下文将位置路径。ContextLoaderServlet同ContextLoaderListener一样使用'contextConfigLocation'参数。
ContextLoaderServlet简介
先看看spring官方网上的信息:
Bootstrap servlet to start up Spring's root WebApplicationContext. Simply delegates to ContextLoader.
This servlet should have a lower load-on-startup
value in web.xml
than any servlets that access the root web application context.
Note that this class has been deprecated for containers implementing Servlet API 2.4 or higher, in favor of ContextLoaderListener.
According to Servlet 2.4, listeners must be initialized before load-on-startup servlets. Many Servlet 2.3 containers already enforce this behavior. If you use such a container, this servlet can be replaced with ContextLoaderListener. Else or if working with a Servlet 2.2 container, stick with this servlet.
(大意是说,这个servlet是启动spring容器的一个servlet,必须把启动优先级调到0,就是比所有的servlet都先启动,ContextServlet最好用在servlet2.4或以上虽然2.3有支持)