• 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
  • 相关阅读:
    如何用一款产品推动「品牌的惊险一跃」?
    JdbcTemplate环境准备_java培训
    如何让GPT不再胡说八道
    sql存储引擎
    FreeRTOS学习笔记--概述
    Linux实操篇-RPM 与 YUM
    左神算法(二)
    【Unity3D】UGUI之Dropdown
    fcpx插件:82种复古电影胶卷框架和效果mFilm Matte
    【21天python打卡】第12天 网络爬虫(3)
  • 原文地址:https://blog.csdn.net/qq_32091929/article/details/125500238