• Java框架(三)--Spring IoC容器与Bean管理(5)--bean scope属性及bean的生命周期


    bean scope属性详解

    bean scope属性

    bean scope属性用于决定对象何时被创建与作用范围。
    bean scope配置将影响容器内对象的数量。
    bean scope默认值singleton(单例),指全局共享同一个对象实例。
    默认情况下bean会在IoC容器创建后自动实例化,全局唯一。

    scope用法

    在这里插入图片描述

    bean scope属性清单

    在这里插入图片描述

    singleton单例示意图

    在这里插入图片描述
    singleton在容器是单例多线程执行,存在线程安全风险
    singleton的线程安全问题。
    在这里插入图片描述

    prototype多例示意图

    在这里插入图片描述
    prototype在容器中多实例,占用更多资源,不存在线程安全问题。

    singleton与prototype对比

    在这里插入图片描述

    bean scope的实际应用

    在com.ql.spring.ioc.dao包下创建类

    package com.ql.spring.ioc.dao;
    
    public class UserDao {
        public UserDao() {
            System.out.println("UserDao已创建:"+this);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后在applicationContext.xml中添加配置

    <bean id="userDao" class="com.ql.spring.ioc.dao.UserDao">
    </bean>
    
    • 1
    • 2

    然后在SpringApplication中获取容器

    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    //UserDao已创建:com.ql.spring.ioc.dao.UserDao@2096442d
    
    • 1
    • 2

    表明scope为单例模式(默认)时IoC初始化时就创建对象。
    所有给bean添加属性scope="prototype"再执行就不会输入创建的信息了

        <bean id="userDao" class="com.ql.spring.ioc.dao.UserDao" scope="prototype"/>
    
    • 1

    现在在SpringApplication中添加两个获取bean实例,就会创建两次对象了

    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    UserDao userDao1 = context.getBean("userDao", UserDao.class);
    UserDao userDao2 = context.getBean("userDao", UserDao.class);
    /*
    UserDao已创建:com.ql.spring.ioc.dao.UserDao@28feb3fa
    UserDao已创建:com.ql.spring.ioc.dao.UserDao@42e26948
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在com.ql.spring.ioc.service包下创建UserService

    package com.ql.spring.ioc.service;
    
    import com.ql.spring.ioc.dao.UserDao;
    
    public class UserService {
        private UserDao userDao;
    	public UserService() {
            System.out.println("UserService已创建:"+this);
        }
        public UserDao getUserDao() {
            return userDao;
        }
    
        public void setUserDao(UserDao userDao) {
        	System.out.println("调用setUserDao:"+userDao);
            this.userDao = userDao;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    然后在applicationContext.xml中添加配置

    <bean id="userDao" class="com.ql.spring.ioc.dao.UserDao" scope="prototype"/>
    <bean id="userService" class="com.ql.spring.ioc.service.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>
    
    • 1
    • 2
    • 3
    • 4

    然后在SpringApplication中获取容器

    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    /*
    UserService已创建:com.ql.spring.ioc.service.UserService@5a61f5df
    UserDao已创建:com.ql.spring.ioc.dao.UserDao@5034c75a
    调用setUserDao:com.ql.spring.ioc.dao.UserDao@5034c75a
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    得出添加scope="prototype"属性后,只有被使用的时候才会被实例化。
    如果applicationContext.xml改成如下

        <bean id="userDao" class="com.ql.spring.ioc.dao.UserDao" scope="prototype"/>
        <bean id="userService" class="com.ql.spring.ioc.service.UserService" scope="prototype">
            <property name="userDao" ref="userDao"/>
        </bean>
    
    • 1
    • 2
    • 3
    • 4

    然后SpringApplication改成如下,输出为

    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
            System.out.println("========IoC容器已经被初始化========");
            UserService userService1 = context.getBean("userService", UserService.class);
            UserService userService2 = context.getBean("userService", UserService.class);
            UserService userService3 = context.getBean("userService", UserService.class);
            UserService userService4 = context.getBean("userService", UserService.class);
    /**
    ========IoC容器已经被初始化========
    UserService已创建:com.ql.spring.ioc.service.UserService@1753acfe
    UserDao已创建:com.ql.spring.ioc.dao.UserDao@39c0f4a
    调用setUserDao:com.ql.spring.ioc.dao.UserDao@39c0f4a
    UserService已创建:com.ql.spring.ioc.service.UserService@27c20538
    UserDao已创建:com.ql.spring.ioc.dao.UserDao@72d818d1
    调用setUserDao:com.ql.spring.ioc.dao.UserDao@72d818d1
    UserService已创建:com.ql.spring.ioc.service.UserService@6e06451e
    UserDao已创建:com.ql.spring.ioc.dao.UserDao@59494225
    调用setUserDao:com.ql.spring.ioc.dao.UserDao@59494225
    UserService已创建:com.ql.spring.ioc.service.UserService@6e1567f1
    UserDao已创建:com.ql.spring.ioc.dao.UserDao@5cb9f472
    调用setUserDao:com.ql.spring.ioc.dao.UserDao@5cb9f472
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在实际项目中,Dao、Service、Controller具体的类为单例的,因为Dao类作为Service类属性,在Service类中是稳定不变的,所以并不会出现线程安全的问题。

    bean的生命周期

    在这里插入图片描述
    首先在com.ql.spring.ioc.entity包下创建Order实体类

    package com.ql.spring.ioc.entity;
    
    public class Order {
        private Float price;
        private Integer quantity;
        private Float total;
    
        public Order() {
            System.out.println("创建Order对象,"+this);
        }
    
        public void init(){
            System.out.println("执行init()方法");
            total = price * quantity;
        }
    
        public void pay(){
            System.out.println("订单金额为:"+total);
        }
    
        public Float getPrice() {
            return price;
        }
    
        public void setPrice(Float price) {
            System.out.println("设置price为:"+price);
            this.price = price;
        }
    
        public Integer getQuantity() {
            return quantity;
        }
    
        public void setQuantity(Integer quantity) {
            System.out.println("设置quantity为:"+quantity);
            this.quantity = quantity;
        }
    
        public Float getTotal() {
            return total;
        }
    
        public void setTotal(Float total) {
            this.total = total;
        }
    
        public void destroy(){
            System.out.println("释放与订单对象相关的资源");
        }
    }
    
    
    • 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
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    然后在applicationContext.xml中配置

    <bean id="order1" class="com.ql.spring.ioc.entity.Order" init-method="init" destroy-method="destroy">
        <property name="price" value="19.8"/>
        <property name="quantity" value="1000"/>
    </bean>
    
    • 1
    • 2
    • 3
    • 4

    然后SpringApplication中获取容器和bean

    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    System.out.println("========IoC容器已经被初始化========");
    Order order1 = context.getBean("order1", Order.class);
    order1.pay();
    ((ClassPathXmlApplicationContext)context).registerShutdownHook();
    /**
    创建Order对象,com.ql.spring.ioc.entity.Order@52af6cff
    设置price为:19.8
    设置quantity为:1000
    执行init()方法
    ========IoC容器已经被初始化========
    订单金额为:19800.0
    释放与订单对象相关的资源
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    【目标定位】基于matlab多机EKF+时差和频差无源定位【含Matlab源码 2057期】
    java毕业设计开题报告论文基于SSM框架医院医疗住院管理信息系统
    SpringBoot Cors配置+原理分析(corsfilter)
    idea10个常用的Debug技巧
    LLM 面试总结
    【 2023华为杯C题】大规模创新类竞赛评审方案研究(思路、代码......)
    DAZ To UMA⭐五.模型在Blender中的配置教程
    建模助手|说一说关于Revit的基础知识
    Spring IOC容器实例化Bean整体流程图
    人工神经网络的算法原理,最简单的神经网络算法
  • 原文地址:https://blog.csdn.net/qq_32091929/article/details/125500238