当前位置: 首页 > 面试题库 >

Spring创建一个单例的多个实例?

伏业
2023-03-14
问题内容

我有一个自动相互连接的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;
}

所有这些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'

我知道我的bean相互交叉引用,但是我希望Spring框架尊重singleton范围并初始化一次singleton
bean,然后将其自动连接到任何需要它的人。

一个有趣的事实是,如果我将老式private构造函数与public static Foo getInstance访问器一起使用,则可以正常工作-
在上下文设置过程中不会引发异常

FWIW,我在o.s.c.s.ClassPathXmlApplicationContext(String ...configLocations)构造器中使用Spring版本3.0.5(也尝试过3.1.2,结果相同)。

我可以轻松地将代码转换为使用静态初始值设定项,但我想了解为什么Spring会这样表现。这是一个错误吗?

编辑: 一些其他调查显示

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

上面对我来说,这表明这是一个与@Autowired实现有关的Spring错误。我将发布到Spring社区论坛,并在这里发布任何有用的信息。


问题答案:

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

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



 类似资料:
  • 问题内容: 我有一个自动相互连接的Spring bean图。大大简化了图示: 所有这些bean都没有指定范围,这暗示它们是单例(使它们成为显式单例不会改变任何东西,我已经尝试过)。 问题在于,在实例化 单个应用程序上下文之后 ,的实例和包含的 不同 实例。怎么会这样 我试图为它创建public no args构造函数,并且调试已确认创建了多次。所有这些创建的堆栈跟踪都在这里。 我还尝试过为Spri

  • 我不知道这里发生了什么事。我有一个包含列表的单例bean。当我向列表中添加项目时,内容总是一致的。然而,当我从另一个服务调用该列表上的get时,它返回一个具有不同java id的空列表。 下面是类的定义方式: 两者的区别是: add方法是从侦听新消息并调用相应处理程序的bean调用的。get是从另一个bean调用的,该bean在事件发生后处理数据。当我一个接一个地调用这两个对象时,列表具有不同的I

  • 本文向大家介绍创建一个类Person的简单实例,包括了创建一个类Person的简单实例的使用技巧和注意事项,需要的朋友参考一下 创建一个类Person,包含以下属性:姓名(name)、年龄(age)、朋友(friends数组)、问候(sayhi方法,输出问候语,例如:“你好!”)、交朋友(addFriend方法,向friends里添加一个值),然后创建两个此类的实例:“小张“,22,[“小李”,”

  • 一个简单的问题,但我找不到答案。我有一个FXML文件,我想多次实例化。每个副本都需要自己的句柄,以便我可以更改其中的数据。假设,这与在刚创建的类上使用“new”关键字完全一样。 到目前为止,在我的尝试中,我已经能够创建fxml文件的多个副本,但只有一个控制器,因此调用方法意味着更改发生在所有副本上。 我是否必须为同一fxml文件的每个副本创建一个新控制器? 提前感谢 编辑 我正在研究这个想法的代码

  • 问题内容: 我在使用此软件包的脚本中遇到问题: 我找不到错误后写了这个小小的testscript,结果是执行cronjobs的次数是预期的两倍: 运行它给我这个输出: 有谁知道我如何能在不重复的情况下创建大量的Gocron作业? 谢谢 :) 问题答案: 还可以吧 将开始已经重新开始的作业,因此要解决我的问题,我不得不将脚本更改为此: 我希望这对遇到相同问题的任何人有所帮助!

  • org.hibernate.Criteria接口表示特定持久类的一个查询。Session 是 Criteria 实例的工厂。 Criteria crit = sess.createCriteria(Cat.class); crit.setMaxResults(50); List cats = crit.list();