当前位置: 首页 > 知识库问答 >
问题:

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

穆远
2023-03-14

当使用Spring Framework时,我怀疑在下面提到的场景中会创建多少实例:

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”具有单例作用域。因此,有一个单例bean引用了一个具有会话范围或原型范围的bean。

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

如果有人能解释这是如何工作的,那将是非常有帮助的。

谢了达薇亚

共有3个答案

闾丘照
2023-03-14

首先,我认为用相同的bean id同时定义会话和原型范围的bean是无效的。

就你而言:一个

一般情况下:根据访问bean的方式:

@Component
class MySingletonBean{
    @Autowired
    MyPrototypeBean b;
}

@Component
class MySingletonBean{
    @Autowired
    MyPrototypeBean b;

    @Autowired
    MyPrototypeBean bSecondInstance;

}

或更多

@Component
class MySingletonBean{
    @Autowired
    javax.inject.Provider<MyPrototypeBean> providerOfB;

    void accessMultipleInstances(){
       MyPrototypeBean bInstance1 = providerOfB.get();
       MyPrototypeBean bInstance2 = providerOfB.get();
       MyPrototypeBean bInstance3 = providerOfB.get();
       //.....

    }

}

注意:MyPrototypeBean被认为已标记为:@Scope(scopeName=ConfigurableBeanFactory.Scope\u PROTOTYPE)。如果省略它,那么在上述所有情况下,都将引用同一个单例实例。

每次一次。

根据这个答案,spring将自动创建一个代理,该代理根据会话的不同针对不同的实例。

这意味着在上述所有情况下,当您在同一个会话中时,您将访问同一个实例。

对我来说,这样的事情更有意义:

<bean id="a" class="A">
    <property name="b" ref="b"/>
    <property name="b2" ref="b2"/>
</bean>
<bean id="b" class="B" scope="session"/> or
<bean id="b2" class="B" scope="prototype"/>

在这种情况下,您将为b每个会话获得一个实例,为b2获得一个也是唯一的实例,因为您从单例中使用它,并且您不使用提供程序或类似的模式。

霍伟彦
2023-03-14

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

1)查找方法注入

2)范围代理

请参阅此处的更多详细信息

范安歌
2023-03-14

单例范围

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

换句话说,当您定义一个bean定义并将其范围限定为一个singleton,那么Spring-IoC容器将创建该bean定义的对象的一个实例。这个实例将被存储在这样的单例bean的缓存中,对该命名bean的所有后续请求和引用都将导致返回缓存对象。

会议范围

有了上述bean定义,Spring容器将为单个HTTP会话生存期创建bean的全新实例。

根据Spring框架参考,当一个“寿命更长的”(本例中为单例bean)的类需要注入另一个寿命相对较短的类(会话范围bean)时,需要采用不同的方法。原型的方法不同

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

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

<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对象。

请参阅此以了解更多信息。

具有原型bean依赖项的单例bean

查找方法注入

当您使用依赖于原型bean的单例范围的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方法注入是容器重写容器托管bean上的方法的能力,以返回容器中另一个命名bean的查找结果。lookup通常涉及一个原型bean,如前一节所述的场景。Spring框架通过使用来自CGLIB库的字节码生成动态生成覆盖该方法的子类来实现该方法注入。

请参阅查找方法注入。

请参阅更详细的示例和信息。

 类似资料:
  • > 在EJB3.0及其之前的版本中,该问题是如何处理的? 如果它保留了客户端特定的会话状态,那么单个实例将拥有所有客户端(试图并发访问)的特定数据?它会安全吗?? 如果我们可以在其他会话bean中使用静态最终变量和静态初始值设定项块或静态方法来初始化它们(因为静态变量也是每个类的数据,而不是每个实例的数据),以便跨bean共享公共数据,那么单例会话bean需要什么呢? 在singleton中使用业

  • Spring具有bean类型/作用域,如 -singleton bean(每个应用程序上下文只有一个bean), -prototype bean(每个请求一个新bean) 现在,如果在单例bean中有对原型bean的引用,是否有办法在对单例bean的每个请求中获得一个新的原型bean(在单例bean中)。< br >如果是,配置会是什么样的?

  • 我刚接触Spring,正在尝试理解“将一个原型bean注入一个单例bean”的概念。根据我在singleton中的理解,每个Spring IoC容器只有一个实例,不管您检索它多少次。,因为仍未实例化。我开发了以下示例,其中在单个bean中给出了原型bean的参考,如下所示: RequestProcessor.java requestValidator.java 如何解决?我的理解正确吗? 另一种方

  • 我不知道这是否是实现我的解决方案的更好方法: 该类是可序列化的,因为我从数据库的Json中获取内容,并将内容映射到对象GetFromJson中(我只需要在数据库中执行一次查询)。因为这个原因,我需要在我所有的应用程序中使用对象,因为这个原因,我认为我需要使用一个单例 有人给我发布了一个库来从数据库中获取JSON。JSON对象解析为,因此我创建了我的类。 现在我有很多rest服务,在我的rest服务

  • 我是spring的新手,我正在尝试修改我的应用程序来实现spring框架。我的请求是为每一个新请求创建一个新bean,然后在后面的代码中引用该bean,以便从单个bean中为其设置值。我正在尝试将bean声明为prototype,并使用查找方法在我的单例bean中引用该bean。但我的问题是,当稍后尝试获取创建的原型bean以设置值时,我看到它在获取bean时再次创建新的bean。 下面是我的原型

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