69

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

我所说的例子

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

9 回答 9

100

spring 规范中,支持五种类型的 bean 范围:

1. 单例(默认*)

将单个 bean 定义限定为每个 Spring 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 的上下文中有效。

<bean />*default 表示标签中没有明确提供范围。在这里阅读更多关于它们的信息:http: //static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html

于 2013-07-11T16:58:32.247 回答
34

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

支持 5 种 bean 范围:

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

  2. 原型:每次请求时它都会返回一个新的 bean 实例。它不存储任何缓存版本,如单例。 在此处输入图像描述

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

    在此处输入图像描述

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

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

大多数情况下,你可能只处理 Spring 的核心作用域——单例原型,默认作用域是单例

于 2016-01-12T14:29:44.247 回答
12

只是想更新一下,在 Spring 5 中,如Spring docs中所述,Spring 支持 6 个作用域,其中四个仅在您使用 Web 感知 ApplicationContext 时可用。

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

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

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

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

application 将单个 bean 定义限定为 ServletContext 的生命周期。仅在 Web 感知 Spring ApplicationContext 的上下文中有效。

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

于 2017-10-13T08:12:18.820 回答
7

Spring 文档描述了以下标准范围

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

原型:将单个 bean 定义限定为任意数量的对象实例。

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

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

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

也可以使用CustomScopeConfigurer. 一个例子是flowSpring Webflow 添加的范围。

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

于 2013-07-11T16:59:40.160 回答
6

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

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

原型- 将单个 bean 定义限定为任意数量的对象实例。

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

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

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

于 2013-07-11T17:00:06.933 回答
2

根据现有五个范围的文档Spring-Cloud-Config还有一个额外的范围。它是@RefreshScope

这是 的简短描述RefreshScope

当配置发生更改时,标记为 @RefreshScope 的 Spring @Bean 会得到特殊处理。此功能解决了仅在初始化时才注入配置的有状态 bean 的问题。例如,如果在通过环境更改数据库 URL 时 DataSource 具有打开的连接,您可能希望这些连接的持有者能够完成他们正在做的事情。然后,下一次从池中借用连接时,它会使用新的 URL 获得一个。

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

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

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

于 2018-09-16T15:49:04.547 回答
2

@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();
    }
}

和主应用程序:

@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 容器创建了一个对象实例。但是,当我们将范围更改为@Scope("prototype")Configuration 类时,结果是:null因为 Spring IoC 容器在发出对该 bean 的请求时会创建该对象的新 bean 实例。

于 2019-12-08T11:55:22.663 回答
0

关于原型bean:

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

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

于 2018-03-02T16:24:10.410 回答
0

还添加了websocket范围:

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

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

于 2020-06-05T04:22:44.090 回答