bean的范围机制是可扩展的;你可以定义自己的scope,或者甚至重新定义已经存在的scopes,虽然后面的一种是一个很坏的编码习惯并且你不能重写内置的singleton和prototype范围。
创建一个自定义的scope
为了将自定义范围集成到Spring容器中,你需要实现org.springframework.beans.factory.config.Scope
接口,将在这章中描述。对于如何实现自定义的范围,请看Spring框架自身提供的Scope实现和其文档,详细介绍了实现自定义范围需要调用的方法。
Scope接口有四个方法:从Scope中获取对象,移除对象,销毁对象。下面的方法从指定scope中返回对象。session 范围的实现,例如,返回会话范围的beans(如果其不存在,这个方法返回这个bean的一个新的实例,不过了需要绑定到会话中用于将来的引用)。
Object get(String name,ObjectFactory objectFactory)
下面的方法从指定的scope中移除对象。例如,session范围实现,从指定的会话中移除了session范围的bean。虽然应该返回对象,但是如果指定名的对象没有发现将返回为null)
Object remove(String name)
下面的方法注册范围执行的回调,当范围销毁时或者在范围内指定对象销毁时。
void registerDestructionCallback(String name, Runnable destructionCallback)
下面的方法返回指定scope的会话标识。每个scope的标识是不同的。对于会话范围的实现,这个标识为会话标识。
String getConversationId()
自定义范围的用法
在你定义了一个或者更多的Scope实现后,你需要使得Spring容器能够知道这些新的scope。使用下面的方法将一个新的scope注册到Spring容器中。
void registerScope(String scopeName, Scope scope);
这个方法在ConfigurableBeanFactory
接口中申明,对于大部分ApplicationContext实现借助BeanFactory属性是可用的。
registerScope方法的第一个参数是指定scope的唯一命名;容器自身内遮阳的命名的例子是singleton和prototype。第二个参数是你希望注册和使用的自定义Scope的的一个实际实例。
假定你写了自定义的Scope实现,并按照如下注册
下面的例子使用了SimpleThreadScope,包含在Spring中,但是默认没有注册。与你自定义实现的scope是相同的。
Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);
之后了 你创建了bean定义,还有自定义Scope的范围规则。
<bean id="..." class="..." scope="thread">
对于自定义Scope的实现,不受限于Scope的程序化编程。你也可以使用
CustomScopeConfigurer
类分开注册。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
<bean id="bar" class="x.y.Bar" scope="thread">
<property name="name" value="Rick"/>
<aop:scoped-proxy/>
</bean>
<bean id="foo" class="x.y.Foo">
<property name="bar" ref="bar"/>
</bean>
</beans>
当在一个FactoryBean实现中放置<aop:scoped-proxy/>
,那么返回有范围的工厂bean自身,而不是由getObject()返回的对象。