Spring Bean作用域是如何被解读的?

2026-05-26 01:131阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1782个文字,预计阅读时间需要8分钟。

Spring Bean作用域是如何被解读的?

目录+Spring中Bean的作用域或范围主要分为五种+(1)被声明为singleton的bean+(2)被声明为prototype的bean+(3)使用注解定义bean的作用域+(4)请求作用域+(5)会话作用域+(6)全局

目录
  • 目前Spring Bean的作用域或者说范围主要有五种
  • (1)被声明为singleton的bean
  • (2)被声明为prototype的bean
  • (3)使用注解定义 bean 的作用域
  • (4)请求作用域
  • (5)会话作用域
  • (6)全局作用域
  • (7)自定义作用域

在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="www.springframework.org/schema/beans"        xmlns:xsi="www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="         www.springframework.org/schema/beans 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中的消息,因为这时的消息已经由第一个对象初始化了。

在单例中,每个SpringIoC容器只有一个实例,无论创建多少个对象,调用多少次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="www.springframework.org/schema/beans" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" www.springframework.org/schema/beans 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文件修改一下。

Spring Bean作用域是如何被解读的?

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="www.springframework.org/schema/beans" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xmlns:context="www.springframework.org/schema/context" xsi:schemaLocation="www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans-4.2.xsd www.springframework.org/schema/context 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监听器接口,该监听器监听www.springframework.org/schema/beans" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xmlns:aop="www.springframework.org/schema/aop" xsi:schemaLocation="www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans.xsd www.springframework.org/schema/aop 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>

以上就是SpringBean作用域的一些基本信息。仅为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

本文共计1782个文字,预计阅读时间需要8分钟。

Spring Bean作用域是如何被解读的?

目录+Spring中Bean的作用域或范围主要分为五种+(1)被声明为singleton的bean+(2)被声明为prototype的bean+(3)使用注解定义bean的作用域+(4)请求作用域+(5)会话作用域+(6)全局

目录
  • 目前Spring Bean的作用域或者说范围主要有五种
  • (1)被声明为singleton的bean
  • (2)被声明为prototype的bean
  • (3)使用注解定义 bean 的作用域
  • (4)请求作用域
  • (5)会话作用域
  • (6)全局作用域
  • (7)自定义作用域

在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="www.springframework.org/schema/beans"        xmlns:xsi="www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="         www.springframework.org/schema/beans 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中的消息,因为这时的消息已经由第一个对象初始化了。

在单例中,每个SpringIoC容器只有一个实例,无论创建多少个对象,调用多少次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="www.springframework.org/schema/beans" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" www.springframework.org/schema/beans 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文件修改一下。

Spring Bean作用域是如何被解读的?

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="www.springframework.org/schema/beans" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xmlns:context="www.springframework.org/schema/context" xsi:schemaLocation="www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans-4.2.xsd www.springframework.org/schema/context 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监听器接口,该监听器监听www.springframework.org/schema/beans" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" xmlns:aop="www.springframework.org/schema/aop" xsi:schemaLocation="www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans.xsd www.springframework.org/schema/aop 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>

以上就是SpringBean作用域的一些基本信息。仅为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。