Spring创建单例的多个实例?

min*_*das 16 java singleton spring autowired applicationcontext

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

<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;
}
Run Code Online (Sandbox Code Playgroud)

所有这些bean都没有指定范围,这意味着它们是单例(使它们显式单例不会改变任何东西,我已经尝试过了).

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

我试图创建public no args构造函数,Foo并且已经确认已经多次创建调试Foo.所有这些创作的堆栈跟踪都在这里.

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

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'
Run Code Online (Sandbox Code Playgroud)

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

有趣的事实是,如果我使用private带有public static Foo getInstance访问器的旧学校构造函数,这很好用 - 在上下文设置期间不会抛出异常.

FWIW,我正在使用Spring版本3.0.5(也尝试使用3.1.2,结果相同)和o.s.c.s.ClassPathXmlApplicationContext(String ...configLocations)构造函数.

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

编辑:一些额外的调查显示

  • 初始化应用程序上下文后,所有后续请求context.getBean(Foo.class) 始终返回相同的实例Foo.
  • @Autowired用setter 替换(这个bean的大约20个用法)仍会导致该对象的多个构造,但是所有依赖项都使用相同的引用注入.

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

roo*_*kit 13

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

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

  • 您能否提供 spring 单例将加载两次的最小示例? (2认同)