实例变量的Spring范围用法

时间:2016-06-02 15:16:40

标签: java spring web-services spring-mvc

我们正在实现spring服务,@ Webservice层是singleton,它调用的是一个'Service'层,它是一个原型。 Service层有很多实例变量,所以认为它是一个原型是理想的,但是,看起来原型只被实例化一次,因为@Webservice层是单例。

什么类型的@Scope适合我们?我们在服务层上有很多实例变量,我们很难将它们作为本地方法,因为很多代码都需要改变。

如果我将所有图层都设为单例,那么两个线程共享实例变量吗?

1 个答案:

答案 0 :(得分:4)

给定一个带有注入目标的单例bean,Spring将初始化bean并立即注入field / method / constructor。如果该注入目标是原型bean,Spring将只执行一次。

据推测,您需要在单例处理的每个动作或事件上使用新的原型bean。你需要一个AOP作用域代理。这在Scoped proxies and dependencies的Spring章节中有记载。使用配置的范围代理,Spring将注入代理而不是原型bean。

代理本身会将对它的所有调用委托给原型bean,每次都是一个新实例。

使用注释配置,您可以使用

配置@Bean@Component
@Scope(scopeName = BeanDefinition.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)

这告诉Spring使用代理配置bean,该代理将继承目标的实际类类型并成为原型。

当你注射它时

@Autowired
private MyPrototypeBean bean;

bean将保留对代理对象的引用。然后,您可以调用方法

bean.method();

,这将委托给一个新实例。这意味着每次通话

bean.method();
bean.method();
bean.method();

将操作一个新实例,上例中的三个新实例。如果您只想要一个实例来调用这些方法,则可以从代理中提取它。请参阅提供的解决方案here

MyPrototypeBean target = null;
if (AopUtils.isJdkDynamicProxy(proxy)) {
    target = (MyPrototypeBean) ((Advised)proxy).getTargetSource().getTarget();
} // won't work for CGLIB classes AFAIK (gotta search)