有一个公开加密功能的服务。我们不需要清理,也不希望每次/每次会话都创建对象。但是每个线程我需要一个单独的对象。
在Web应用程序中 - 范围是否为Web容器的线程池?
春季3和4实施是否相同?
我们计划使用它的另一个地方是缓存SimpleDateFormat对象。再次不需要清理方法。
答案 0 :(得分:4)
从3.0版开始,Spring有一个基本的线程范围概念:SimpleThreadScope
。看起来它可以满足您的要求,但它有一些局限性:
如果您可以满足这些限制,则可以以编程方式注册范围:
Scope threadScope = new SimpleThreadScope();
appContext.getBeanFactory().registerScope("thread", threadScope);
或在xml config中:
<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>
这在Spring 3和Spring 4中的工作方式相同。如果要在单例bean中注入线程范围的bean,则必须在其上声明一个aop scoped-proxy:
<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>
(Spring Framework Reference Documentation中的所有示例)。
如果您需要进行一些清理,可以查看显示SimpleThreadScope
增强版本的此文档Spring by Example Custom Thread Scope Module。
但是我不确定你真的想要那个,除非所有线程不断使用线程范围的bean,否则内存不是真正的问题。因为在该设计模式中,如果一次只有一个会话需要bean,但它由多个线程服务(假设其他请求不需要bean),所有线程将获得bean的不同实例,而使用池只会使用一个实例。
您将在SO How to pool objects in Spring?的另一篇文章中找到使用CommonsPoolTargetSource
和Apache公共池的示例。摘自帖子:
<bean id="simpleBeanTarget" class="com.bean.SimpleBean" scope="prototype"/>
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
<property name="targetBeanName" value="simpleBeanTarget" />
<property name="maxSize" value="2" />
</bean>
<bean id="simpleBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="poolTargetSource" />
</bean>
该示例使用ProxyFactoryBean
提供aop代理,以允许在单个bean中注入simpleBean
,前提是它作为接口注入。
答案 1 :(得分:1)
ThreadLocal有线程范围的对象。 其次,SimpleDateFormat和DateFormats通常不同步。所以要注意那里的线程问题。 顺便说一句,当你说“每个线程”时,你的意思是每个请求?正如the java doc for SimpleThreadScope所述,通常最好在Web环境中使用RequestScope。
Spring可以使用specific scopes创建bean,例如原型,请求,您可能需要考虑。正如@Sairam所提到的,生命周期管理也值得一提。
答案 2 :(得分:0)
在spring框架中,为了获得每个线程的单独对象,我们可以通过将bean作为原型来实现这一点。
来自reference。,
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
Spring 3&amp;图4分别针对该特定情况。关于对象的清理,原型范围的行为与来自同一参考文档的不同。
与其他作用域相比,Spring不管理原型bean的完整生命周期:容器实例化,配置和组装原型对象,并将其交给客户端,没有该原型实例的进一步记录。因此,尽管无论范围如何都在所有对象上调用初始化生命周期回调方法,但在原型的情况下,不会调用已配置的销毁生命周期回调。客户端代码必须清理原型范围的对象并释放原型bean所持有的昂贵资源。
答案 3 :(得分:-1)
为您提供解决方案: