Spring创建单例的多个实例? [英] Spring creating multiple instances of a singleton?

查看:517
本文介绍了Spring创建单例的多个实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Spring bean的图表,它们互相自动装配。重度简化插图:

I have a graph of Spring beans which autowire each other. Heavily simplified illustration:

<context:annotation-config/>
<bean class="Foo"/>
<bean class="Bar"/>
<bean class="Baz"/>

...

public class Foo {
   @Autowired Bar bar;
   @Autowired Baz baz;
}

public class Bar {
   @Autowired Foo foo;
}

public class Baz {
   @Autowired Foo foo;
}

所有这些bean都没有指定范围,这意味着它们是单身人士(让它们成为明确的单例并不会改变任何东西,我已经尝试过了。

All of these beans don't have scope specified which imply they are singletons (making them explicit singletons doesn't change anything, I've tried).

问题是在实例化单个应用程序上下文之后, Bar Baz 的实例包含 c> Foo的不同实例。怎么会发生这种情况?

The problem is that after the instantiation of a single application context, instances of Bar and Baz contain different instances of Foo. How could this happen?

我试图为 Foo 创建public no args构造函数,并且调试已确认 Foo 不止一次创建。所有这些创作的堆栈跟踪都是此处

I have tried to create public no args constructor for Foo and debugging has confirmed Foo is created more than once. The stack trace for all of these creations is here.

我还尝试为Spring启用调试日志记录,并在所有其他行中启用以下内容:

I have also tried to enable debug logging for Spring, and among all other lines, got the following:

DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'

I理解我的bean是相互交叉引用的,但我希望Spring框架能够尊重单例范围并初始化一个单例bean,然后将它自动装配给任何想要它的人。

I understand that my beans are cross-referencing each other, but I would expect Spring framework to respect singleton scope and initialize a singleton bean once, and then autowire it to whoever wants it.

有趣的事实,如果我使用旧学校私人构造函数与 public static Foo getInstance accessor,这很好用 - 在上下文设置期间不会抛出任何异常。

The interesting fact that if I use old school private constructor with public static Foo getInstance accessor, this works just fine - no exceptions are thrown during the context setup.

FWIW,我正在使用Spring版本3.0.5(也尝试使用3.1.2,结果相同)与 oscsClassPathXmlApplicationContext(String ... configLocations)构造函数。

FWIW, I am using Spring version 3.0.5 (also tried with 3.1.2, same results) with o.s.c.s.ClassPathXmlApplicationContext(String ...configLocations) constructor.

我可以轻松地将我的代码转换为使用静态初始化程序,但我想理解为什么Spring会以这种方式运行。这是一个错误吗?

I can easily convert my code to use static initializer but I want to understand why would Spring behave this way. Is this a bug?

编辑:一些额外的调查表明


  • 初始化应用程序上下文后,对 context.getBean(Foo.class)的所有后续请求 始终返回相同的实例 Foo

  • 用setter替换 @Autowired (约20次使用这个bean)仍会产生这个对象的多个构造,但是所有依赖项都注入了相同的引用。

  • After the application context is initialized, all subsequent requests to context.getBean(Foo.class) always return the same instance of Foo.
  • Replacing @Autowired with setters (about 20 usages of this bean) still results multiple constructions of this object, but all dependencies are injected with the same reference.

对我来说,这表明这是一个与 @Autowired 实现有关的Spring bug。如果我设法获得任何有用的东西,我将发布到Spring社区论坛并发回这里。

To me above suggests that this is a Spring bug pertaining to @Autowired implementation. I am going to post to Spring community forums and post back here if I manage to obtain anything useful.

推荐答案

子上下文(s)如果您不小心上下文,可以重新实例化相同的单例bean:组件扫描注释(还有其他Spring上下文扫描注释,如MVC和其他)。在Web应用程序中使用Spring servlet时,这是一个常见问题,请参阅为什么DispatcherServlet创建另一个应用程序上下文?

Child context(s) can reinstantiate the same singleton beans if you are not careful with context:component-scan annotations (there are other Spring context scan annotations as well such as MVC ones and others). This is a common problem when using Spring servlets in web applications, see Why DispatcherServlet creates another application context?

确保您没有在子环境中重新扫描您的组件,或者您只扫描特定的包/注释并从中排除所述包/注释根上下文组件扫描。

Make sure you are not re-scanning your components in child contexts, or you are scanning only specific packages/annotations and excluding said packages/annotations from root context component scan.

这篇关于Spring创建单例的多个实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆