• Spring中Bean的作用域


    文章目录


    Spring Bean的作用域

    • singleton:单例模式

      IOC容器仅创建一个Bean实例,后续每次从IOC容器中获取的都是同一个Bean实例。Spring中的Bean默认都是单例模式的。

    • prototype:原型模式(又叫做多例模式)

      每次从IOC容器中获取的都是一个新的Bean实例。

    • request:HTTP请求

      每一次HTTP请求都会产生一个新的Bean实例,该Bean实例仅在当前HTTP请求中共享。

    • session:HTTP会话

      每一次HTTP会话都会产生一个新的Bean实例,该Bean实例仅在当前HTTP会话中共享。

    • global-session:全局HTTP会话

      所有的Session共享一个Bean实例。仅在基于portlet的web应用中才有意义,Spring5已经没有了。

    单例Bean与原型Bean对比

    • 使用:

      • 单例bean只有第一次创建新的bean(保存在Spring容器中),后面都会复用该bean,所以不会频繁创建对象。
      • 原型bean每次都会新创建。
    • 线程安全:

      • 单例bean非线程安全
      • 原型bean线程安全

    对单例bean的误解:

    单例bean并不是指Spring容器中只能有一个该类型的bean(该类型可以有多个id不同的bean),而是指根据条件(name、type)从Spring容器中获取bean时,如果容器中有则直接使用该bean,容器中没有才会创建bean。

    举例说明:

    public class UserService {
    
    }
    
    
    @Configuration
    public class TestConfiguration {
    
        @Bean("userService1")
        public UserService userService1() {
            return new UserService();
        }
    
        @Bean("userService2")
        public UserService userService2() {
            return new UserService();
        }
    }
    
    
    @SpringBootApplication
    public class SpringbootApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringbootApplication.class, args);
            System.out.println(applicationContext.getBean("userService1", UserService.class));
            System.out.println(applicationContext.getBean("userService2",UserService.class));
            System.out.println(applicationContext.getBean("userService1", UserService.class));
            System.out.println(applicationContext.getBean("userService2",UserService.class));
            System.out.println(applicationContext.getBean("userService1", UserService.class));
            System.out.println(applicationContext.getBean("userService2",UserService.class));
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    打印日志

    com.joker.test.autowiredtest.UserService@68cc6319
    com.joker.test.autowiredtest.UserService@3d0f4ac4
    com.joker.test.autowiredtest.UserService@68cc6319
    com.joker.test.autowiredtest.UserService@3d0f4ac4
    com.joker.test.autowiredtest.UserService@68cc6319
    com.joker.test.autowiredtest.UserService@3d0f4ac4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    分析可知,单例UserService在Spring容器中有两个实例bean,重复获取也不会新增实例,而是使用Spring容器中原有的两个实例bean。

    单例bean非线程安全

    单例bean是存在线程问题的。当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。

    解决办法:

    1. 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐)。
    2. 避免在类中定义可变的成员变量(不推荐,因为不太现实)。
  • 相关阅读:
    阿里云易立:以增效促降本,容器服务全面进入智能化时代
    医学图像匹配,c++计算归一化互相关
    【开发日记】MySQL-Explain学习日记
    【数据结构】栈与队列面试题(C语言)
    LeetCode --- 1480. Running Sum of 1d Array 解题报告
    多位大佬合力讲解23种设计模式,这不是轻松拿下
    跨域解决方案
    Prometheus----3
    负载均衡 - F5
    重新认识面向对象——Java写了五年,你真的弄明白什么是面向对象了吗?不,你一直都是在面向过程编程
  • 原文地址:https://blog.csdn.net/m0_67403272/article/details/126516476