返回顶部
首页 > 资讯 > 后端开发 > Python >解读Spring Bean的作用域
  • 682
分享到

解读Spring Bean的作用域

Spring BeanBean作用域Spring Bean作用域 2022-11-13 19:11:28 682人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录目前spring Bean的作用域或者说范围主要有五种(1)被声明为singleton的bean(2)被声明为prototype的bean(3)使用注解定义 bean 的作用域(

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

目前Spring Bean的作用域或者说范围主要有五种

作用域描述
singleton在spring ioc容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。
prototype每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。
request每次Http请求都会创建一个新的Bean,该作用域仅适用于WEB的Spring WebApplicationContext环境。
session同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。
application限定一个Bean的作用域为ServletContext的生命周期。该作用域仅适用于web的Spring WebApplicationContext环境。

(1)被声明为singleton的bean

如果bean的作用域的属性被声明为singleton,那么Spring Ioc容器只会创建一个共享的bean实例。对于所有的bean请求,只要id与该bean定义的相匹配,那么Spring在每次需要时都返回同一个bean实例。

Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,singleton作用域是Spring中的缺省作用域。你可以在 bean 的配置文件中设置作用域的属性为 singleton,如下所示:

<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="singleton">
    <!-- collaborators and configuration for this bean Go here -->
</bean>

单例的例子

1.首先创建一个bean。

package com.spring.demo;
public class  SingletonBean{
   private String message;
   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}

2.在Spring的配置文件中配置该bean。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="SingletonBean" class="com.spring.demo.SingletonBean" scope="singleton"></bean>
    <!-- 或者 -->
    <!--  <bean id="SingletonBean" class="com.spring.demo.SingletonBean" ></bean> -->
</beans>

测试该Bean是否为单例的。

package com.spring.demo;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.junit.Test;
 
public class TestBean {
 
    @Test
    public void textUser()
    {
        //1.获取spring文件
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean.xml");
        //2.由配置文件返回对象
        SingletonBean singletonBeanA = (SingletonBean)context.getBean("SingletonBean");
        singletonBeanA.setMessage("I'm object A");
        singletonBeanA.getMessage();
        SingletonBean singletonBeanB = (SingletonBean)context.getBean("SingletonBean");
        singletonBeanB.getMessage();
    }
}

运行结果:

由于SingletonBean是单例的作用域,创建两个SingletonBean对象,第二个对象获取SingletonBean对象中的消息值得时候即使是由一个新的getBean()方法来获取,也可以不用设置对象中消息的值就可以直接获取SingletonBean中的消息,因为这时的消息已经由第一个对象初始化了。

在单例中,每个Spring IoC容器只有一个实例,无论创建多少个对象,调用多少次getMessafe( )方法获取它,它总是返回同一个实例。 

(2)被声明为prototype的bean

当一个bean的作用域为prototype,表示一个bean定义对应多个对象实例。

声明为prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。

prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。

根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

prototype的例子。

还是上面的代码。其他代码不变,把Bean.xml文件中bean的作用域由singleton改为prototype。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="SingletonBean" class="com.spring.demo.SingletonBean" scope="prototype"></bean>
   
</beans>

执行代码,程序的执行结果为:

从图上可以看出在SingletonBeanA中设置的参数值在SingletonBeanB就获取不到了,说明这两个对象现在返回的就不是同一个对象实例。

(3)使用注解定义 bean 的作用域

除了在Bean.xml文件中定义bean的作用域之外,还可以使用注解来定义 bean 的作用域。

1.在Bean中加上注解。

package com.spring.demo;
 
import org.springframework.context.annotation.Scope;;
import org.springframework.stereotype.Component;
 
@Component("SingletonBean")
@Scope("prototype")
public class SingletonBean {
    private String message;
    public void setMessage(String message){
        this.message  = message;
    }
    public void getMessage(){
        System.out.println("Your Message : " + message);
    }
}
  • @Component("SingletonBean")注解是告诉Spring这是一个bean。
  • @Scope("prototype")注解是告诉Spring该bean的作用域是prototype。

2.bean.xml文件修改一下。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.2.xsd">
   
    <context:component-scan base-package="com.spring.demo" />
 
</beans>

<context:component-scan base-package="com.spring.demo" />就是扫描com.spring.demo包中的所有类的注解。

测试代码不用变,运行测试。

和在bean.xml中直接定义bean和其作用域是一样的效果。其他作用域也可以使用注解方式声明bean的作用域。

request,session和application这三个作用域都是基于web的Spring WebApplicationContext实现的,只有在web环境下(比如XmlWebApplicationContext)中才能使用。 如果开发者仅仅在常规的Spring IoC容器中比如ClassPathXmlApplicationContext在中使用这些作用域,那么将会抛出一个IllegalStateException来说明使用了未知的作用域。

也就是当用户使用Spring的WebApplicationContext时,除了使用常规的singleton和prototype作用域之外,还可以使用另外3种Bean的作用域,即request,session和application。

在使用Web应用环境相关的Bean作用域时,必须在Web容器中进行一些额外的配置:

1.如果开发者使用了Spring Web mvc框架的话,每一个请求都会通过Spring的DispatcherServlet来处理,也就没有其他特殊的初始化配置,就不需要配置了。DispatcherServlet已经包含了相关的状态。

2.如果开发者使用的是低版本Web容器比如Servlet 2.5的web容器,请求不是通过Spring的DispatcherServlet(比如jsF或者Struts)来处理的。那么开发者需要注册org.springframework.web.context.request.RequestContextListener或者ServletRequestListener。可以在web.xml中增加如下的Listener声明: 

<web-app>
    ...
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    ...
</web-app>

ServletContextListener只负责监听web容器启动和关闭的事件,而RequestContextListener实现了ServletRequestListener监听器接口,该监听器监听http请求事件。Web服务器接收到的每一次请求都会通知该监听器。 

而在Servlet 3.0以后,这些都能够通过WebApplicationInitializer接口来实现配置。

3.如果不使用Listener,也可以考虑使用Spring的RequestContextFilter,通过http过滤器进行配置,在url-pattern中对所有的页面进行过滤。也是在web.xml中进行配置。

<web-app>
    ...
    <filter>
        <filter-name>requestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>requestContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>

配置完这些额外的配置之后,就可以使用另外的3种bean的作用域了。 

(4)请求作用域

请求作用域参考如下的Bean定义

<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>

Spring容器会在每次用到loginAction来处理每个HTTP请求的时候都会创建一个新的LoginAction实例。也就是说,loginActionBean的作用域是HTTP Request级别的。 

当http请求调用作用域为request的bean的时候,每增加一个HTTP请求,Spring就会创建一个新的bean,在请求处理完成之后便及时销毁这个bean。

开发者可以随意改变实例的状态,因为通过loginAction请求来创建的其他实例根本看不到开发者改变的实例状态,所有创建的Bean实例都是根据独立的请求来的。

(5)会话作用域

会话作用域参考如下的Bean定义

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

Spring容器会在每次调用到userPreferences时,在一个单独的HTTP会话周期来创建一个新的UserPreferences实例。换言之,userPreferencesBean的作用域是HTTP Session级别的。

Session中所有http请求共享同一个请求的bean实例。Session结束后就销毁bean。 在request-scoped作用域的Bean上,开发者可以随意的更改实例的状态。同样,使用从同一个userPreferences bean定义创建的其他HTTP Session实例在看不到不是自己的内部状态的修改,因为他们是单个的HTTP会话。

每个Session请求都会创建新的userPreferences实例,所以开发者更改一个Bean的状态,对于其他的Bean仍然是不可见的。

(6)全局作用域

全局作用域参考如下的Bean定义

<bean id="appPreferences" class="com.foo.AppPreferences" scope="application"/>

Spring容器会在整个web应用范围使用到appPreferences的时候创建一个新的AppPreferences的实例。也就是说,appPreferencesBean是在ServletContext级别的,作为常规的ServletContext属性。这种作用域在一些程度上来说和Spring的单例作用域相似,但是也有如下不同之处:

1.application作用域是每个ServletContext中包含一个,而不是每个SpringApplicationContext之中包含一个(某些应用中可能包含不止一个ApplicationContext)。

2.application作用域仅仅作为ServletContext的属性可见,单例Bean是ApplicationContext可见。

接下来再来简单的学习下在Spring当中如何自定义作用域:

在Spring 2.0中,Spring的Bean作用域机制是可以扩展的,这意味着,你不仅可以使用Spring提供的预定义Bean作用域,还可以定义自己的作用域,甚至重新定义现有的作用域(不提倡这么做,而且你不能覆盖内置的singleton和prototype作用域)

(7)自定义作用域

除了使用Spring已经定义好的作用域之外,还可以自定义bean的作用域。

要底线自定义作用域

1.首先需要实现自定义Scope类。

首先要先实现org.springframework.beans.factory.config.Scope这个接口,要将自定义scope集成到Spring容器当中就必须要实现这个接口。接口中有两个常用的方法,分别用于底层存储机制获取和删除这个对象。

2.在实现一个或多个自定义Scope并测试通过之后,接下来便是如何让Spring容器来识别新的作用域。reGISterScope方法就是在Spring容器中用来注册新的作用域。

void registerScope(String scopeName, Scope scope);

其中:第一个参数是与作用域相关的全局唯一的名称,第二个参数是准备实现的作用域的实例,就是实现Scope接口的实例。

比如实现Scope接口的类为SimpleThreadScope,要实现的自定义的bean的作用域的名称为“thread”,那就可以这么写。

Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);

3.在实现和注册自定义的scope类之后,就可以通过如下类似的Bean定义来使用自定义的Scope:

<bean id="..." class="..." scope="thread">

另外,在自定义的Scope中,开发者也不限于仅仅通过编程方式来实现自定义的bean的作用域,也可以在Spring的配置文件中配置和使用自定义作用域和,比如配置CustomScopeConfigurer实例实现自定义的作用域,声明作用域名称为“thread”,就可以在xml文件中做如下类似的定义。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
 
    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="thread">
                    <bean class="org.springframework.context.support.SimpleThreadScope"/>
                </entry>
            </map>
        </property>
    </bean>
 
    <bean id="bar" class="x.y.Bar" scope="thread">
        <property name="name" value="Rick"/>
        <aop:scoped-proxy/>
    </bean>
 
    <bean id="foo" class="x.y.Foo">
        <property name="bar" ref="bar"/>
    </bean>
 
</beans>

以上就是Spring Bean作用域的一些基本信息。仅为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: 解读Spring Bean的作用域

本文链接: https://lsjlt.com/news/170447.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 解读Spring Bean的作用域
    目录目前Spring Bean的作用域或者说范围主要有五种(1)被声明为singleton的bean(2)被声明为prototype的bean(3)使用注解定义 bean 的作用域(...
    99+
    2022-11-13
    Spring Bean Bean作用域 Spring Bean作用域
  • Spring中Bean的作用域是什么
    这篇文章给大家介绍Spring中Bean的作用域是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、Bean的作用域首先我们来讲一下有关于bean的作用域,一般情况下,我们书写在IOC容器中的配置信息,会在我们的I...
    99+
    2023-06-20
  • Spring中的Bean作用域是什么
    本文小编为大家详细介绍“Spring中的Bean作用域是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring中的Bean作用域是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。概述scope用来声明...
    99+
    2023-06-30
  • Spring Bean作用域实例分析
    这篇文章主要介绍“Spring Bean作用域实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring Bean作用域实例分析”文章能帮助大家解决问题。Bean作用域bean是存在作用域的...
    99+
    2023-07-02
  • Spring简明分析Bean作用域
    目录Bean作用域一、singleton(单例模式)二、protoType(原型模式)Bean作用域   经过前面的学习,我们可以知道bean是存在作用域的。 &...
    99+
    2024-04-02
  • 一文搞懂Spring中的Bean作用域
    目录概述Singletonprototyperequestsessionapplication概述 scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,即容器在对...
    99+
    2024-04-02
  • Spring中Bean的作用域与生命周期详解
    目录一、Bean的作用域1、单实例Bean声明2、多实例Bean声明二、Bean的生命周期1、bean的初始和销毁2、bean的后置处理器总结一、Bean的作用域 首先我们来讲一下有...
    99+
    2024-04-02
  • 详解Spring中Bean的作用域与生命周期
    目录一、Bean的作用域二、Bean的生命周期使用代码演示Bean的生命周期一、Bean的作用域 通过Spring容器创建一个Bean的实例时,不仅可以完成Bean的实例化,还可以使...
    99+
    2024-04-02
  • Java Spring中Bean的作用域及生命周期
    目录1.Bean的作用域1.1 被修改的Bean案例1.2 为什么使用单例模式作为默认作用域1.3 作用域1.4 Bean的6种作用域1.5 设置作用域2.Spring执行流程和Be...
    99+
    2022-11-13
    Java Spring中Bean的作用域 Spring中Bean的生命周期
  • 解读Spring定义Bean的两种方式:<bean>和@Bean
    目录前言    1.通过XML的方式来生成一个bean1)创建entity,命名为Student2)在beans.xml中定义Student3)测试be...
    99+
    2023-05-14
    Spring定义Bean Spring <bean> Spring @Bean
  • Spring中Bean的作用域和自动装配方式
    目录Bean的作用域默认配置scope = “singleton”scope = “prototype”Bean的自动装配通过name自动装配通过type自动装配Bean的作用域 S...
    99+
    2024-04-02
  • Spring中Bean的作用域与生命周期是什么
    这篇文章主要讲解了“Spring中Bean的作用域与生命周期是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring中Bean的作用域与生命周期是什么”吧!一、Bean的作用域通过S...
    99+
    2023-06-22
  • 探秘Spring中Bean的注解宝典:解读存取Bean的相关注解及用法
    目录 存储Bean对象@Controller(控制器存储)@Service(服务存储)@Repository(仓库存储)@Component(组件存储)@Configuration(配置存储)Bean重命名Bean 获取B...
    99+
    2023-08-16
    spring java 后端 开发语言 青少年编程
  • Spring Bean中的作用域和生命周期实例分析
    这篇文章主要介绍“Spring Bean中的作用域和生命周期实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring Bean中的作用域和生命周期实例分析”文章能帮助大...
    99+
    2023-07-02
  • Spring IOC容器Bean的作用域及生命周期是什么
    本篇内容介绍了“Spring IOC容器Bean的作用域及生命周期是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!bean作用域bean...
    99+
    2023-06-30
  • Java Bean的作用域,生命周期和注解
    目录Bean的作用域singleton作用域Bean的生命周期1.创建Bean的实现类2.配置Bean 3.测试生命周期 Bean的装配方式基于XML配置的装配基于注解的装配1.@C...
    99+
    2024-04-02
  • Java之Spring Bean作用域和生命周期源码分析
    这篇文章主要讲解了“Java之Spring Bean作用域和生命周期源码分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java之Spring Bean作用域和生命周期...
    99+
    2023-07-05
  • Java面试突击之Bean作用域详解
    目录1.作用域2.作用域分类2.1 singleton2.2 prototype2.3 request2.4 session2.5 application3.作用域设置总结Sprin...
    99+
    2024-04-02
  • Spring的@Bean注解怎么使用
    今天小编给大家分享一下Spring的@Bean注解怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Spring @Be...
    99+
    2023-07-02
  • spring中@Configuration和@Bean注解的用法
    目录概要定义注意概要 @Configuration里边定义@Bean,@Configuration相当于一个xml配置文件,@Bean就是xml中的<bean/> 定义 ...
    99+
    2023-05-20
    spring @Configuration spring @Bean spring注解
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作