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

2021-03-09 05:28

阅读:449

标签:user   控制台   http   分布   prot   system   val   play   splay   

1、Bean 的作用域介绍

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

  1. singleton:单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。
  2. prototype:原型模式(多例模式),每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例,即每次调用getBean()时。
  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 元素中的 scope 属性 或者 @Scope 注解 来设置,例如:

  • XML 中设置作用域:
  • 注解设置作用域: @Scope("prototype") 或者 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)


       在上述五种作用域中,实际开发中 singleton 和 prototype 是最常用的两种,接下来将对这两种作用域进行详细讲解。

  • singleton 作用域:singleton 是 Spring 容器默认的作用域,当一个 Bean 的作用域为 singleton 时,Spring 容器中只会存在一个共享的 Bean 实例,并且所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,就只会返回 Bean 的同一个实例。通常情况下,这种单例模式对于无会话状态的 Bean(如 DAO 层、Service 层)来说,是最理想的选择。
  • prototype 作用域:使用 prototype 作用域的 Bean 会在每次请求该 Bean 时都会创建一个新的 Bean 实例。因此对需要保持会话状态的 Bean应该使用 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如下所示:

       ③、测试代码,这里分别获取了三个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);
    }
}

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

技术图片

       可以很明显的发现,这三个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);
    }
}

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

技术图片

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

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

标签:user   控制台   http   分布   prot   system   val   play   splay   

原文地址:https://www.cnblogs.com/tanghaorong/p/14185723.html


评论


亲,登录后才可以留言!