除了Singleton和Prototype两个原生Bean作用域外,早在Spring2.0版本上,就增加了具有web生命周期的bean 作用域:request、session和 global session。但不支持ServletContext(即Web中Application)作用域。尽管Singleton有一定的全局作用意义,但在Sping容器中支持Application,以IOC方式注入和访问ServletContext中的Bean对象,对于WEB开发还是很有用处的。
本文利用Spring自定义作用域机制,扩展了其bean作用域。简单的实现了对Application作用域的支持。
Holder类,使用类静态变量方式持有ServletContext
package rtl.ioc.spring;
import javax.servlet.ServletContext;
public class ApplicationHolder{
private static ServletContext ctx=null;
public static void setApplication(ServletContext sctx){
ctx=sctx;
}
public static void setApplicationAttribute(String name,Object obj){
ctx.setAttribute(name, obj);
}
public static Object getApplicationAttribute(String name) {
return ctx.getAttribute(name);
}
public static void removeApplicationAttribute(String name) {
ctx.removeAttribute(name);
}
}
ApplicationScope实现org.springframework.beans.factory.config.Scope (Bean作用域接口)
package rtl.ioc.spring;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
public class ApplicationScope implements Scope{
public Object get(String name, ObjectFactory objectFactory){
Object scopedObject = ApplicationHolder.getApplicationAttribute(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
ApplicationHolder.setApplicationAttribute(name, scopedObject);
}
return scopedObject;
}
public Object remove(String name) {
Object scopedObject = ApplicationHolder.getApplicationAttribute(name);
if (scopedObject != null) {
ApplicationHolder.removeApplicationAttribute(name);
return scopedObject;
}
return null;
}
public void registerDestructionCallback(String name, Runnable callback){ }
public String getConversationId() {
return null;
}
}
使用ServletContextListener向ApplicationHolder类注入ServletContext
package rtl.ioc.spring;
import javax.servlet.*;
public class ApplicationScopeListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event){
ApplicationHolder.setApplication(event.getServletContext());
}
public void contextDestroyed(ServletContextEvent event){}
}
使用CustomScopeConfigurer来进行声明式注册Application作用域
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="application">
<bean class="rtl.ioc.spring.ApplicationScope"/>
</entry>
</map>
</property>
</bean>
使用演示配置形如:
<bean id="ApplicationBean" class="demo.ApplicationBean" scope="application"></bean>