spring IOC容器实例化Bean的方式与RequestContextListener应用

<!--Spring ApplicationContext 载入 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- 使Spring支持request与session的scope,如:<bean id="loginAction" class="com.foo.LoginAction" scope="request"/> -->
	<listener>
	  <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
	</listener>

	<!-- Spring 刷新Introspector防止内存泄露 -->
	<listener>
		<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
	</listener>

这里,在webApplicationContext初始化时,我们已经通过ContextLoaderListener将web容器与spring容器整合,为什么这里又要引入一个额外的RequestContextListener以支持Bean的另外3个作用域呢?

在整合spring容器时使用ContextLoaderListener,它实现了ServletContextListener监听器接口。ServletContextListener只负责监听web容器启动和关闭的事件。

而RequestContextListener实现ServletRequestListener监听器接口,该监听器监听HTTP请求事件,web服务器接收的每一次请求都会通知该监听器。

spring容器的启动和关闭操作由web容器的启动和关闭触发,但如果spring容器中的bean需要request,session,globalsession作用于的支持,spring容器本身就必须获得web容器的HTTP请求事件,以HTTP请求事件驱动Bean作用于的控制逻辑。

 

spring IOC容器实例化Bean的方式有:

singleton 在spring IOC容器中仅存在一个Bean实例,Bean以单实例的方式存在.

spring以容器的方式提供天然的单实例模式功能,任何POJO无须编写特殊的代码仅通过配置就可以了.

注意:spring将Bean的默认作用域定为singleton.

在默认情况下,spring的ApplicationContext容器在启动时,自动实例化所有singleton的Bean并缓存于容器中.

虽然启动时会花费一些时间,但带来两个好处:

首先对Bean提前的实例化操作会及早发现一些潜在的配置问题.

其次Bean以缓存的方式保存,当运行时使用到该Bean时就无须再实例化了,加快了运行效率.

如果用户不希望在容器启动时提前实例化singleton的Bean,可以通过lazy-init属性进行控制:

<bean id="boos1" class="com.baobaotao.scope.Boss" lazy-init="true">

      <property name="car" ref="car"/>

</bean>

lazy-init="true"的Bean在某些情况下依旧会提前实例化:如果该Bean被其它需要提前实例化的Bean引用到,

spring也将忽略延迟实例化的设置.

 

prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean()的操作.

采用scope="prototype"指定非单实例作用域Bean,请看:

<bean id="car" class="com.baobaotao.scope.Car" scope="prototype"/>

<bean id="boss1" class="com.baobaotao.scope.Boss">

     <property name="car" ref="car"/>

</bean>

<bean id="boss2" class="com.baobaotao.scope.Boss">

     <property name="car" ref="car"/>

</bean>

boss1,boss2所引用的都是一个独立的Car实例.

在默认情况下,spring容器在启动时不实例化prototype的Bean.此外,spring容器将prototype的Bean交给调用者后,就不再管理它的生命周期.

 

request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于webApplicationContext环境.

顾名思义,request作用域的Bean对应一个HTTP请求和生命周期。

这样,每次HTTP请求调用到car Bean时,spring容器创建一个新的Car Bean,请求处理完毕后,销毁这个Bean.

 

session 同一个HTTP session共享一个Bean,不同HTTP session使用不同的Bean,该作用域仅适用于webApplicationContext环境.

假设将以上car的作用域调整为session类型:

<bean name="car" class="com.baobaotao.scope.Car" scope="session"/>

这样配置后,car Bean的作用域横跨整个HTTP session,session中所有HTTP请求都共享同一个Car Bean,当HTTP Session结束后,实例才被销毁.

 

globalSession 同一个全局session共享一个Bean,一般用于portlet应用环境,该作用域仅适用于webApplicationContext环境.

globalSession作用域类似于session作用域,不过仅在portlet的web应用中使用.Portlet规范定义了全局Session概念,它被组成portlet web应用的所有子portlet共享.如果不在Portlet web应用环境下,globalSession自然等价于session作有域了。

相关推荐