• 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. 避免在类中定义可变的成员变量(不推荐,因为不太现实)。
  • 相关阅读:
    根目录挂载的/dev/mapper/centos-root分区扩容
    一卷到底,大明哥带你横扫 Netty
    网络安全(黑客)小白学习笔记
    NX二次开发-通过点击按钮来控制显示工具条
    自然语言处理(NLP)技术
    Web Component-自定义元素的生命周期
    Spring Cloud Gateway核心过滤器之请求限流详解
    android edittext正则表达式限制输入内容
    C++数组莫名其妙出现NaN——记一次由C++数组错误初始化导致的问题
    laravel教程
  • 原文地址:https://blog.csdn.net/m0_67403272/article/details/126516476