Bean的作用域

举报
CoderX 发表于 2022/04/06 13:37:10 2022/04/06
【摘要】 Bean的作用域​ 默认情况下,所有Spring Bean都是单例的(整个Spring应用中,Bean的实例只有一个)。可以再<bean>元素中添加scope属性来配置Spring Bean的作用范围。scope作用域范围:作用范围描述singleton默认值,单例模式,表示在 Spring 容器中只有一个 Bean 实例prototype原型模式,表示每次通过 Spring...

Bean的作用域

​ 默认情况下,所有Spring Bean都是单例的(整个Spring应用中,Bean的实例只有一个)。可以再<bean>元素中添加scope属性来配置Spring Bean的作用范围。

scope作用域范围:

作用范围 描述
singleton 默认值,单例模式,表示在 Spring 容器中只有一个 Bean 实例
prototype 原型模式,表示每次通过 Spring 容器获取 Bean 时,容器都会创建一个新的 Bean 实例。
request 每次 HTTP 请求,容器都会创建一个 Bean 实例。该作用域只在当前 HTTP Request 内有效。
session 同一个 HTTP Session 共享一个 Bean 实例,不同的 Session 使用不同的 Bean 实例。该作用域仅在当前 HTTP Session 内有效。
application 同一个 Web 应用共享一个 Bean 实例,该作用域在当前 ServletContext 内有效。 与 singleton 类似,但 singleton 表示每个 IoC 容器中仅有一个 Bean 实例,而一个 Web 应用中可能会存在多个 IoC 容器,但一个 Web 应用只会有一个 ServletContext,也可以说 application 才是 Web 应用中货真价实的单例模式。
websocket websocket 的作用域是 WebSocket ,即在整个 WebSocket 中有效。

注意:在以上 6 种 Bean 作用域中,除了 singleton 和 prototype 可以直接在常规的 Spring IoC 容器(例如 ClassPathXmlApplicationContext)中使用外,剩下的都只能在基于 Web 的 ApplicationContext 实现(例如 XmlWebApplicationContext)中才能使用,否则就会抛出一个 IllegalStateException 的异常。

单例模式singleton

singleton是Spring Ioc容器默认的作用域,此时容器中只会存在一个共享的Bean实例。这个Bean实例会被存储在高速缓存中,所有对于这个Bean的请求和引用,只要id与这个Bean定义相匹配,都会返回这个缓存中的对象实例。

在 Spring 配置文件中,可以使用 <bean> 元素的 scope 属性,将 Bean 的作用域定义成 singleton,其配置方式如下所示:(不声明scope属性默认也是singleton)

<bean id="..." class="..." scope="singleton"/>

代码示例:

  1. 实体类
package org.demo5;

public class SingletonBean {
    private String str;

    public void setStr(String str) {
        this.str = str;
    }
}
  1. 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="singletonBean" class="org.demo5.SingletonBean" scope="singleton">
        <property name="str" value="bdqn"></property>
    </bean>

</beans>
  1. main方法
package org.demo5;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    //private static final Log LOGGER= LogFactory.getLog(MainApp.class);
    public static void main(String[] args) {
        //创建bean工厂
        ApplicationContext context=new ClassPathXmlApplicationContext("demo5beans.xml");
        //取bean
        SingletonBean sBean1=context.getBean("singletonBean",SingletonBean.class);
        SingletonBean sBean2=context.getBean("singletonBean",SingletonBean.class);
        System.out.println(sBean1);
        System.out.println(sBean2);

    }
}

运行结果:

org.demo5.SingletonBean@696da30b
org.demo5.SingletonBean@696da30b

​ 从控制台的输出可以看出,两次获得的 Bean 实例的地址完全一样,这说明 IoC 容器只创建了一个 singletonBean 实例。由于 singleton 是 Spring IoC 容器的默认作用域,因此即使省略 scope 属性,控制台的输出结果也一样的。

原型模式prototype

当Bean定义的作用域为prototype,Spring容器会在每次请求该Bean时,都会创建一个新的Bean实例。

代码示例:

  1. 实体类

    package org.demo5;
    
    public class PrototypeBean {
        private String str;
    
        public void setStr(String str) {
            this.str = str;
        }
    }
    
    
  2. 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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <!--singleton-->
        <bean id="singletonBean" class="org.demo5.SingletonBean" scope="singleton">
            <property name="str" value="singletonBean"/>
        </bean>
    
        <!--prototype-->
        <bean id="prototypeBean" class="org.demo5.PrototypeBean" scope="prototype">
            <property name="str" value="prototypeBean"/>
        </bean>
    
    
    </beans>
    
  3. main方法类

    package org.demo5;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainApp {    //private static final Log LOGGER= LogFactory.getLog(MainApp.class);    public static void main(String[] args) {        //创建bean工厂        ApplicationContext context=new ClassPathXmlApplicationContext("demo5beans.xml");        //singleton        SingletonBean sBean1=context.getBean("singletonBean",SingletonBean.class);        SingletonBean sBean2=context.getBean("singletonBean",SingletonBean.class);        System.out.println(sBean1);        System.out.println(sBean2);        //prototype        PrototypeBean pBean1=context.getBean("prototypeBean",PrototypeBean.class);        PrototypeBean pBean2=context.getBean("prototypeBean",PrototypeBean.class);        System.out.println(pBean1);        System.out.println(pBean2);    }}
    
  4. 运行结果

    org.demo5.PrototypeBean@be35cd9
    org.demo5.PrototypeBean@4944252c
    

    从运行结果可以看出,两次输出的内容并不相同,这说明在 prototype 作用域下,Spring 容器创建了两个不同的 prototypeBean 实例。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。