• Spring详解(十一)----Bean 的作用域


    1、Bean 的作用域介绍

           默认情况下,Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一 一个实例,并且整个 IOC 容器范围内都能共享该实例,所有后续的对象通过getBean() 调用和 Bean 的引用都将返回这个唯一的 Bean 实例。但是如果我们需要不同实例的Bean呢?这时就要提到Bean的作用域了,在Spring中默认的作用域为 Singleton,它是所有 Bean 的默认作用域。而在Spring 中提供了 5 种作用域,它会根据情况来决定是否生成新的对象,如下:

    1. singleton:单例模式,这是 Bean 默认的作用域,使用 singleton 定义的 Bean 在整个 Spring 容器生命周期内只创建这一个 Bean。
    2. prototype:原型模式(多例模式),Spring 容器初始化时不创建 Bean 的实例,而在每次通过getBean获取Bean时都创建一个新的Bean实例并返回。
    3. request:请求模式,用于Web开发,在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效。
    4. session:会话模式,用于Web开发,在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。
    5. global Session(Spring5已经去除了):全局会话模式,在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。一般用于 Porlet 应用环境 , 分布式系统存在全局 session 概念(单点登录),如果不是 porlet 环境,globalSession 等同于 Session。

           =====================================

           我们可以通过XML<bean> 元素中的 scope 属性 或者 @Scope 注解 来设置Bean的作用域,例如:

    • XML 中设置作用域:<bean id="" class="" scope="prototype" />
    • 注解设置作用域: @Scope("prototype") 或者 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

           在上述五种作用域中,实际开发中 singleton 和 prototype 是最常用的两种。

    2、XML配置举例

           ①、首先创建一个User类,代码如下:

    /**
     * 用户实体类
     */
    public class User {
        private int userId;
        private String userName;
        private int userAge;
        private String userPwd;
        private String userAddress;
    
        //getter、setter省略...(这里就不要toString方法了,因为要打印对象的地址)
    }

           ②、在 Spring 的配置文件我们将 scope 属性的值设置为 prototype 多例模式,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.xsd">
        <!--创建一个User实例,作用域设置为prototype 多例模式-->
        <bean id="user" class="com.thr.pojo.User" scope="prototype"/>
    </beans>
    

           ③、测试代码,这里分别获取了三个User对象:

    /**
     * 测试代码
     */
    public class SpringTest {
        public static void main(String[] args) {
            //1.初始化Spring容器,加载配置文件
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            //2.通过容器获取实例
            User user1 =  applicationContext.getBean("user", User.class);
            User user2 =  applicationContext.getBean("user", User.class);
            User user3 =  applicationContext.getBean("user", User.class);
            //3.调用实例中的属性
            System.out.println(user1);
            System.out.println(user2);
            System.out.println(user3);
        }
    }

           ④、运行测试代码,查看控制台打印的结果:

    image

           可以很明显的发现,这三个User对象的地址是不一样的,说明分别创建了三个不同的User对象。

    3、注解配置举例

           ①、首先创建一个User类,代码参考上面的。

           ②、创建PojoConfig类,用来启动容器和注册Bean对象:

    /**
     * 启动容器和注册Bean对象
     */
    @ComponentScan(basePackages = "com.thr.pojo")
    @Configuration
    public class PojoConfig {
        public PojoConfig() {
            System.out.println("PojoConfig容器初始化成功...");
        }
    
        //实例化User对象
        @Bean(name = "user")
        //显示设置单例模式
        @Scope(value = "singleton")
        public User user(){
            return new User();
        }
    }

           ③、测试代码,这里分别获取了三个User对象,注意这里需要使用AnnotationConfigApplicationContext类来获取:

    /**
     * 测试代码
     */
    public class SpringTest1 {
        public static void main(String[] args) {
            //1.初始化Spring容器,通过注解加载
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PojoConfig.class);
            //2.通过容器获取实例
            User user1 =  applicationContext.getBean("user", User.class);
            User user2 =  applicationContext.getBean("user", User.class);
            User user3 =  applicationContext.getBean("user", User.class);
            //3.调用实例中的属性
            System.out.println(user1);
            System.out.println(user2);
            System.out.println(user3);
        }
    }

           ④、运行测试代码,查看控制台打印的结果:

    image

           由于注册 Bean 时Scope设置为 singleton 单例模式,所以创建的多个 User 肯定是同一个,可以发现结果是一样的。

  • 相关阅读:
    接口自动化架构-获取用例
    Windows性能监控工具Perfmon使用指南
    接口自动化架构1-setting
    多进程
    线程锁、守护线程
    多线程
    xlrd模块
    封装写日志的类
    封装redis
    继承
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/14185723.html
Copyright © 2020-2023  润新知