Spring Bean Scopes

时间:2013-07-11 16:55:49

标签: java spring spring-mvc

有人可以解释一下Spring bean中的范围是什么我一直只是使用'原型'但是我可以用其他参数代替吗?

我正在谈论的例子

    <bean id="customerInfoController" class="com.action.customer.Controller" scope="prototype">
    <property name="accountDao" ref="accountDao"/>
    <property name="utilityDao" ref="utilityDao"/>
    <property name="account_usageDao" ref="account_usageDao"/>  
</bean>

9 个答案:

答案 0 :(得分:77)

spring specs开始,支持五种类型的bean范围:

  

<强> 1。单(默认*)

     

将每个Spring的单个bean定义范围限定为单个对象实例   IoC容器。

     

<强> 2。原型

     

将单个bean定义范围限定为任意数量的对象实例。

     

第3。请求

     

将单个bean定义范围限定为单个HTTP的生命周期   请求;这就是每个HTTP请求都有自己的   在单个bean定义的后面创建的bean实例。   仅在Web感知Spring ApplicationContext的上下文中有效。

     

<强> 4。会话

     

将单个bean定义范围限定为HTTP会话的生命周期。   仅在Web感知Spring ApplicationContext的上下文中有效。

     

<强> 5。全球会议

     

将单个bean定义范围限定为全局HTTP的生命周期   会话。通常仅在portlet上下文中使用时有效。只要   在Web感知的Spring ApplicationContext的上下文中有效。

* default表示<bean />标记中未明确提供范围的情况。 在这里阅读更多相关信息:http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html

答案 1 :(得分:19)

在Spring中,bean作用域用于决定应该将哪个类型的bean实例从Spring容器返回给调用者。

支持5种类型的bean作用域:

  1. Singleton:它为每个Spring IoC容器返回一个bean实例。这个单实例存储在这样的单例bean的缓存中,并且该命名bean的所有后续请求和引用都返回缓存的对象。如果bean配置文件中没有指定bean范围,默认指定为单例。

  2. 原型:每次请求时都返回一个新的bean实例。它不存储像singleton这样的任何缓存版本。

  3. 请求:每个HTTP请求返回一个bean实例。

  4. 会话:每个HTTP会话返回一个bean实例(用户级会话)。

  5. GlobalSession :每个全局HTTP会话返回一个bean实例。它仅在Web感知的Spring ApplicationContext(应用程序级别会话)的上下文中有效。

  6. 在大多数情况下,您可能只处理Spring的核心范围 - singleton prototype ,默认范围是 singleton 。< / p>

答案 2 :(得分:7)

只想更新,就像在Spring docs中提到的那样,在Spring 5中,Spring支持6个范围,只有在使用支持Web的ApplicationContext时才有4个范围可用。

  

singleton (默认)将每个Spring IoC容器的单个bean定义范围限定为单个对象实例。

     

<强>原型   将单个bean定义范围限定为任意数量的对象实例。

     

请求   将单个bean定义范围限定为单个HTTP请求的生命周期;也就是说,每个HTTP请求都有自己的bean实例,它是在单个bean定义的后面创建的。仅在Web感知Spring ApplicationContext的上下文中有效。

     

<强>会话   将单个bean定义范围限定为HTTP会话的生命周期。仅在Web感知Spring ApplicationContext的上下文中有效。

     

<强>应用   将单个bean定义范围限定为ServletContext的生命周期。仅在Web感知Spring ApplicationContext的上下文中有效。

     

<强>的WebSocket   将单个bean定义范围限定为WebSocket的生命周期。仅在Web感知Spring ApplicationContext的上下文中有效。

答案 3 :(得分:5)

Spring文档描述了following standard scopes

  

singleton :(默认)将每个Spring IoC容器的单个bean定义范围限定为单个对象实例。

     

prototype :将单个bean定义范围限定为任意数量的对象实例。

     

request :将单个bean定义范围限定为单个HTTP请求的生命周期;也就是说,每个HTTP请求都有自己的bean实例,它是在单个bean定义的后面创建的。仅在Web感知Spring ApplicationContext的上下文中有效。

     

会话:将单个bean定义范围限定为HTTP会话的生命周期。仅在Web感知Spring ApplicationContext的上下文中有效。

     

全局会话:将单个bean定义范围限定为全局HTTP会话的生命周期。通常仅在portlet上下文中使用时有效。仅在Web感知Spring ApplicationContext的上下文中有效。

还可以使用CustomScopeConfigurer创建和配置其他自定义范围。一个例子是Spring Webflow添加的flow范围。

顺便说一句,你认为你总是使用prototype我觉得奇怪的东西。标准范围是singleton,在我开发的应用程序中,我很少需要原型范围。你应该看看这个。

答案 4 :(得分:5)

每个范围的详细说明可在Spring bean scopes中找到。以下是摘要

Singleton - (默认)将每个Spring IoC容器的单个bean定义范围限定为单个对象实例。

prototype - 将单个bean定义范围限定为任意数量的对象实例。

request - 将单个bean定义范围限定为单个HTTP请求的生命周期;也就是说,每个HTTP请求都有自己的bean实例,它是在单个bean定义的后面创建的。仅在Web感知Spring ApplicationContext的上下文中有效。

session - 将单个bean定义范围限定为HTTP会话的生命周期。仅在Web感知Spring ApplicationContext的上下文中有效。

全局会话 - 将单个bean定义范围限定为全局HTTP会话的生命周期。通常仅在portlet上下文中使用时有效。仅在Web感知Spring ApplicationContext的上下文中有效。

答案 5 :(得分:0)

关于原型豆:

  

客户端代码必须清理原型范围的对象并释放   原型bean持有的昂贵资源。得到的   Spring容器释放由原型范围的bean持有的资源,   尝试使用自定义bean后处理器,它包含一个引用   需要清理的豆子。

参考:https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html#beans-factory-scopes-prototype

答案 6 :(得分:0)

根据Spring-Cloud-Config的{​​{3}},在现有五个范围的旁边有一个额外的范围。是@RefreshScope

这是RefreshScope的简短描述:

  

进行配置更改时,标记为   @RefreshScope得到特殊处理。此功能解决了   仅注入其配置的有状态bean问题   当它们初始化时。例如,如果数据源已打开   通过环境更改数据库URL时的连接,您   可能希望这些连接的持有人能够完成   他们在做什么。然后,下次有东西借用   从池中进行连接,它将获得一个带有新URL的地址。

     

有时,甚至可能必须应用@RefreshScope   某些bean上的注释只能被初始化一次。如果是豆   是“不可变的”,您将必须使用   @RefreshScope或在属性键下指定类名   spring.cloud.refresh.extra-refreshable。

     

刷新作用域bean是惰性代理,它们在初始化时会初始化   使用(即调用方法时),并且作用域充当缓存   初始化值。强制Bean在下一个重新初始化   方法调用,必须使它的缓存条目无效。

     

RefreshScope在上下文中是一个bean,并且具有公共   refreshAll()方法通过清除   目标缓存。 / refresh端点公开了此功能(通过   HTTP或JMX)。要通过名称刷新单个bean,还有一个   refresh(String)方法。

答案 7 :(得分:0)

一个简短的示例@Scope("singleton")(默认)和@Scope("prototype")之间有什么区别:

DAO类:

package com.example.demo;

public class Manager {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

配置:

@Configuration
public class AppConfiguration {
    @Bean
    @Scope("singleton")
    public Manager getManager(){
        return new Manager();
    }
}

和MainApp:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.scan("com.example.demo");
        context.refresh();

        Manager firstManager = context.getBean(Manager.class);
        firstManager.setName("Karol");

        Manager secondManager = context.getBean(Manager.class);
        System.out.println(secondManager.getName());
    }

}

在此示例中,即使我们仅为Karol对象设置此名称,结果也将是:firstManager。这是因为Spring IoC容器创建了一个对象实例。但是,当我们在Configuration类中将范围更改为@Scope("prototype")时,结果为:null,因为当请求该bean时,Spring IoC容器会创建该对象的新bean实例。

答案 8 :(得分:0)

还添加了websocket范围:

将单个bean定义的作用域限定为WebSocket的生命周期。仅在可感知网络的Spring ApplicationContext上下文中有效。

根据文档的内容,还有线程范围,默认情况下未注册。