为singleton bean创建了多少个实例,引用了会话bean / prototype bean

时间:2014-07-28 17:04:47

标签: spring instance

我怀疑使用Spring时将在下面提到的场景中创建的实例数量:

bean配置就像这样

  <bean id="a" class="A">
    <property name="b" ref="b"/>
    </bean>

<bean id="b" class="B" scope="session"/> or

 <bean id="b" class="B" scope="prototype"/>

默认情况下,bean“a”具有singleton scope。因此,有一个单例bean,它引用了一个具有会话范围或原型范围的bean。

在这种情况下,如果同时有2个应用程序请求,那么将创建多少个A实例以及将创建多少个B实例?

如果有人可以解释这是如何起作用的话会有很大的帮助吗?

谢谢, 迪夫亚

2 个答案:

答案 0 :(得分:36)

单身范围

当bean是singleton时,将只管理bean的一个共享实例,并且对具有与该bean定义匹配的id或id的bean的所有请求将导致返回一个特定的bean实例Spring容器。

换句话说,当你定义一个bean定义并且它的范围是singleton时,那个bean定义所定义的Spring IoC containercreate exactly one instance of the object。此单个实例将存储在此类单例bean的缓存中,并且该命名bean的所有后续请求和引用将导致返回缓存对象。

会话范围

通过上面的bean定义,Spring容器将为lifetime of a single HTTP Session创建一个全新的bean实例。

根据Spring框架参考,在需要向另一个具有相对较短寿命的类注入“lives longer”(在这种情况下为单例bean)的类的情况下,需要遵循不同的方法。 (会话范围的bean)。原型和方法的方法不同。单身范围虽然。

在XML中,我们想要的是singletonBean实例只应实例化一次,并且应该使用sessionBean注入。但由于sessionBean是会话范围的(这意味着它应该为每个会话重新实例化),配置是不明确的(因为依赖关系是在实例化时设置的,会话范围的值也可以在以后更改)。 / p>

因此,不是使用该类注入,而是注入一个代理,该代理公开与sessionBean完全相同的公共接口。容器将此代理对象注入singletonBean bean,该bean不知道此sessionBean引用是代理。它通过在sessionBean中写入此标记来指定:

<aop:scoped-proxy/>

XML配置:

<bean name="singletonBean" class="somepkg.SingletonBean">
<property name="someProperty" ref="sessionBean"/>
</bean>

<bean name="sessionBean" class="somepkg.SessionBean" scope="session">
<aop:scoped-proxy/>
</bean>

singletonBean实例在依赖注入的sessionBean对象上调用方法时,它实际上是在代理上调用方法。然后,代理从(在这种情况下)HTTP会话中获取真实的sessionBean对象,并将方法调用委托给检索到的真实sessionBean对象。

另请参阅this了解更多信息。

具有原型bean依赖关系的单例bean

查找方法注入

当您在singleton-scoped上使用具有依赖关系的prototype beans bean时,请注意在实例化时解析依赖关系。因此,如果依赖项将prototype-scoped bean注入到单例范围的bean中,则会实例化一个新的原型bean,然后将依赖注入到单例bean中。原型实例是唯一提供给单例范围bean的实例。

但是,假设您希望单例范围的bean在运行时重复获取原型范围的bean的新实例。您不能将原型范围的bean依赖注入到您的单例bean中,因为当Spring容器实例化单例bean并解析并注入其依赖项时,该注入只发生一次。

<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
  <!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
  <lookup-method name="createCommand" bean="command"/>
</bean>

Lookup method注入是容器到override methods on container托管bean的能力,用于返回容器中另一个命名bean的查找结果。 lookup通常涉及prototype bean,如上一节中所述的方案。 Spring Framework通过使用CGLIB library中的字节码生成来实现此方法注入,以动态生成覆盖该方法的子类。

参考lookup method injection

Follow了解更详细的示例和信息。

答案 1 :(得分:0)

如果我们使用问题中提到的方式,春天IOC将创建始终返回与singleton相同的对象,为了在singleton中注入原型bean我们有两种方式

1)查找方法注入

2)Scoped Proxies

查看更多详情here