spring 为引用会话 bean/原型 bean 的单例 bean 创建了多少个实例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25000406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 23:56:01  来源:igfitidea点击:

How many instances created for singleton bean referring to a session bean/prototype bean

springinstance

提问by user1477232

I have a doubt about the number of instances that will be created in the scenario mentioned below, when Spring Framework is used:

我对下面提到的场景中使用 Spring Framework 时会创建的实例数量有疑问:

The bean configuration is like this

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"/>

By default, bean "a" has singleton scope. So there is a singleton bean with a reference to a bean with session scope or prototype scope.

默认情况下,bean "a" 具有singleton scope. 所以有一个单例 bean 引用一个具有会话范围或原型范围的 bean。

In this case, if there are 2 simultaneous requests to the application, then how many instances of A will be created and how many instances of B will be created?

在这种情况下,如果有 2 个并发请求到应用程序,那么将创建多少个 A 实例和多少个 B 实例?

It will be of great help if anyone can explain how this works.

如果有人能解释它是如何工作的,那将会有很大帮助。

Thanks, Divya

谢谢,迪维亚

回答by Ankur Singhal

The singleton scope

单例范围

When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.

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

To put it another way, when you define a bean definition and it is scoped as a singleton, then the Spring IoC containerwill create exactly one instance of the objectdefined by that bean definition. This single instance will be stored in a cache of such singleton beans, and all subsequent requests and references for that named bean will result in the cached object being returned.

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

The session scope

会话范围

With the above bean definition in place, the Spring container will create a brand new instance of the bean , for the lifetime of a single HTTP Session.

有了上面的 bean 定义,Spring 容器将创建一个全新的 bean 实例,用于lifetime of a single HTTP Session.

According to Spring framework reference, a different approach needs to be followed in cases where a class which "lives longer"(singleton bean in this case) needs to be injected with another class having a comparatively shorter life-span(session-scoped bean). The approach is different for prototype & singleton scope though.

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

In your XML, what we want is that the singletonBean instance should be instantiated only once, and it should be injected with sessionBean. But since sessionBeanis session-scoped(which means it should be re-instantiated for every session), the configuration is ambiguous(as the dependencies are set at instantiation time and the session scoped value can change later also).

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

So instead of injecting with that class, its injected with a proxy that exposes the exact same public interface as sessionBean. The container injects this proxy object into the singletonBean bean, which is unaware that this sessionBean reference is a proxy. Its specified by writing this tag in the sessionBean:

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

<aop:scoped-proxy/>

XML Configuration:

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>

When a singletonBeaninstance invokes a method on the dependency-injected sessionBean object, it actually is invoking a method on the proxy. The proxy then fetches the real sessionBean object from (in this case) the HTTP Session, and delegates the method invocation onto the retrieved real sessionBean object.

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

Alse please refer thisfor more info.

也请参考这里了解更多信息。

Singleton beans with prototype-bean dependencies

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

Lookup Method Injection

查找方法注入

When you use singleton-scopedbeans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scopedbean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.

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

However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.

但是,假设您希望单例范围的 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 methodinjection is the ability of the container to override methods on containermanaged beans, to return the lookup result for another named bean in the container. The lookuptypically involves a prototype beanas in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB libraryto generate dynamically a subclass that overrides the method.

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

Refer lookup method injection.

参考查找方法注入

Followfor more detailed example and information.

关注更详细的示例和信息。

回答by Surya

If we use the way as mentioned in question spring IOC will create always return the same object as singleton, In order to inject prototype bean inside singleton we have two way

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

1) Lookup method injection

1)查找方法注入

2) Scoped Proxies

2) 范围代理

see more detail here

在此处查看更多详细 信息