ChatGPT解决这个技术问题 Extra ChatGPT

Spring Bean 范围

有人可以解释一下 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>
请参阅Bean Scopes
我想添加一个更新:根据新的 Spring 版本,docs。 spring 现在有 6 个作用域:Singleton、Prototype、Request、Session、Application、WebSocket。 recommended official spring doc. link ...并且...如果您对官方 spring 文档的链接不满意,这里是 another simple explanation

K
KNU

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

1. singleton(default*) 将单个 bean 定义限定为每个 Spring IoC 容器的单个对象实例。 2. 原型 将单个 bean 定义限定为任意数量的对象实例。 3. request 将单个 bean 定义限定到单个 HTTP 请求的生命周期;也就是说,每个 HTTP 请求都将有自己的 bean 实例,该实例是在单个 bean 定义的后面创建的。仅在 Web 感知 Spring ApplicationContext 的上下文中有效。 4. session 将单个 bean 定义限定为 HTTP Session 的生命周期。仅在 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


“Web 感知 Spring ApplicationContext”是扩展 ApplicationContext 的 WebApplicationContext。除了@JunedAhsan 提到的额外作用域之外,还有一个 getServletContext() 方法来 Return the standard Servlet API ServletContext for this application.
D
Divyesh Kanzariya

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

支持 5 种 bean 范围:

Singleton :它为每个 Spring IoC 容器返回一个 bean 实例。这个单个实例存储在此类单例 bean 的缓存中,并且该命名 bean 的所有后续请求和引用都返回缓存的对象。如果在 bean 配置中未指定 bean 范围文件,默认为单例。原型:每次请求时它都会返回一个新的 bean 实例。它不存储任何缓存版本,如单例。 Request :它为每个 HTTP 请求返回一个 bean 实例。会话:它为每个 HTTP 会话(用户级会话)返回一个 bean 实例。 GlobalSession :它为每个全局 HTTP 会话返回一个 bean 实例。它仅在 Web 感知 Spring ApplicationContext(应用程序级会话)的上下文中有效。

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


h
heyxh

只是想更新一下,在 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 的上下文中有效。


总共有 6 个范围,前两个可以在没有网络感知的情况下使用?如果是这样,那么您如何说 6 个中的 5 个只有在您使用 Web 感知 ApplicationContext 时才可用?
你说的对。他犯了一个错误,他说的是 5 而不是 4。
C
Community

Spring 文档 描述了 following standard scopes

单例:(默认)将单个 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 创建和配置其他自定义范围。一个示例是 Spring Webflow 添加的 flow 范围。

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


V
Vikas V

可以在 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 的上下文中有效。


M
Michu93

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


z
zappee

根据 Spring-Cloud-Configdocumentation,在现有的五个范围之外还有一个额外的范围。它是@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) 方法。


e
emon

关于原型bean:

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

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


g
gai-jin

还添加了 websocket 范围:

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

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