Spring |(二)IOC相关内容 | bean

文章目录

  • 📚bean基础配置
    • 🐇bean的id和class
    • 🐇bean的name属性
    • 🐇bean作用范围scope配置
    • 🐇bean基础配置小结
  • 📚bean实例化
    • 🐇构造方法实例化(常用)
    • 🐇静态工厂实例化
    • 🐇实例工厂与FactoryBean
  • 📚bean的生命周期
    • 🐇生命周期设置
    • 🐇销毁操作未调用解决方法
    • 🐇Spring提供的生命周期控制接口

学习来源:黑马程序员SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术

📚bean基础配置

🐇bean的id和class

  • id:使用容器可以通过id值获取对应的bean,在一个容器中id值唯一
  • class:bean的类型,即配置的bean的全路径类名
    在这里插入图片描述

🐇bean的name属性

  • name属性,定义bean的别名,可定义多个,使用逗号、分号、空格分隔。
    在这里插入图片描述

  • 配置别名:打开spring的配置文件applicationContext.xml。

    <!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
    <bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
    </bean>
    
  • 根据名称容器获取bean对象(对应名称必须在spring配置文件中存在)

    public class AppForName {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            //此处根据bean标签的id属性和name属性的任意一个值来获取bean对象
            BookService bookService = (BookService) ctx.getBean("service4");
            bookService.save();
        }
    }
    

🐇bean作用范围scope配置

  • 验证思路:同一个bean获取两次,将对象打印到控制台,看打印出的地址值是否一致。

    BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
    BookDao bookDao2 = (BookDao) ctx.getBean("bookDao");
    System.out.println(bookDao1);
    System.out.println(bookDao2);
    

    打印结果:
    在这里插入图片描述

  • 默认情况下,Spring创建的bean对象都是单例的。

  • 在Spring配置文件中,配置scope属性来实现bean的非单例创建。

    <bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope=""/>
    
    • 将scope设置为singleton
      在这里插入图片描述
    • 将scope设置为prototype
      在这里插入图片描述
  • bean默认为单例? bean为单例是指在Spring的IOC容器中只会有该类的一个对象。这避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高。

  • 线程安全问题?

    • 如果对象是有状态对象,即该对象有成员变量可以用来存储数据,那所有请求线程共用一个bean对象会存在线程安全问题。
    • 如果对象是无状态对象,即该对象没有成员变量进行数据存储的,方法中的局部变量在方法调用完成后会被销毁,不会存在线程安全问题。
  • 表现层对象、业务层对象、数据层对象、工具对象适合交给容器进行管理。

  • 封装实例的域对象,因为会引发线程安全问题,不适合交给容器进行管理。

🐇bean基础配置小结

在这里插入图片描述

📚bean实例化

以下涉及到的project结构如下:
在这里插入图片描述

🐇构造方法实例化(常用)

  • bean本质上就是对象,对象在new的时候会使用构造方法完成,创建bean也是使用构造方法完成的。
  • 步骤1:准备一个BookDao和BookDaoImpl类,即【提供可访问的构造方法】。
    public interface BookDao {
        public void save();
    }
    
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ...");
        }
    
    }
    
  • 步骤2:将类【配置】到Spring容器
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    	<!--方式一-->
    	<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    
    </beans>
    
  • 步骤3:编写运行程序
    public class AppForInstanceBook {
        public static void main(String[] args) {
            ApplicationContext ctx = new 
                ClassPathXmlApplicationContext("applicationContext.xml");
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
        }
    }
    
  • Spring容器在创建对象的时候走的是类的无参构造方法,且底层用的是反射,能访问类中的私有构造方法。真正在使用这种方式的时候,我们什么也不需要做。

🐇静态工厂实例化

  • 步骤1:准备一个OrderDao和OrderDaoImpl类。
    public interface OrderDao {
        public void save();
    }
    
    public class OrderDaoImpl implements OrderDao {
        public void save() {
            System.out.println("order dao save ...");
        }
    }
    
  • 步骤2:创建一个工厂类OrderDaoFactory并提供一个【静态方法】。
    //静态工厂创建对象
    public class OrderDaoFactory {
        public static OrderDao getOrderDao(){
            return new OrderDaoImpl();
        }
    }
    
  • 步骤3:在spring的【配置】文件application.properties中添加以下内容↓
    <!--方式二-->
    <bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
    
    在这里插入图片描述
  • 步骤4:在AppForInstanceOrder运行类,使用从IOC容器中获取bean的方法进行运行测试
    public class AppForInstanceOrder {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");
            orderDao.save();
        }
    }
    

  • 静态工厂方法的意义?
    • 主要的原因是在工厂的静态方法中,我们除了new对象还可以做其他的一些业务操作,这些操作必不可少(直接new对象的方式就无法添加其他的业务内容),比如:
      public class OrderDaoFactory {
          public static OrderDao getOrderDao(){
              System.out.println("factory setup....");//模拟必要的业务操作
              return new OrderDaoImpl();
          }
      }
      
  • 静态工厂实例化一般是用来兼容早期的一些老系统,所以了解为主

🐇实例工厂与FactoryBean

  • 步骤1:准备一个UserDao和UserDaoImpl类。
    public interface UserDao {
        public void save();
    }
    
    public class UserDaoImpl implements UserDao {
    
        public void save() {
            System.out.println("user dao save ...");
        }
    }
    
  • 步骤2:创建一个【实例工厂】类OrderDaoFactory并提供一个普通方法(注意此处和静态工厂的工厂类不一样的是不是静态方法)。
    public class UserDaoFactory {
        public UserDao getUserDao(){
            return new UserDaoImpl();
        }
    }
    
  • 步骤3:在spring的【配置】文件中添加以下内容↓
    <!--方式三-->
    <bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>
    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
    
    在这里插入图片描述
  • 步骤4:在AppForInstanceUser运行类,使用从IOC容器中获取bean的方法进行运行测试。
    public class AppForInstanceUser {
        public static void main(String[] args) {
            ApplicationContext ctx = new 
                ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao userDao = (UserDao) ctx.getBean("userDao");
            userDao.save();
        }
    }
    

  • 以上就是实例工厂实例化的方式,Spring为了简化这种配置方式提供了一种叫FactoryBean的方式来简化开发。
    在这里插入图片描述

  • 步骤1:【创建一个UserDaoFactoryBean的类】,【实现FactoryBean接口】,重写接口的方法。

    public class UserDaoFactoryBean implements FactoryBean<UserDao> {
        //【代替】原始实例工厂中创建对象的方法
        public UserDao getObject() throws Exception {
            return new UserDaoImpl();
        }
        //返回所创建类的Class对象
        public Class<?> getObjectType() {
            return UserDao.class;
        }
    }
    
    • 这里造出的对象【默认是单例】的,如果要改成非单例,则加上下
      public boolean isSingleton() {
          return false;
      }
      
  • 步骤2:在Spring的配置文件中进行配置。

    <!--方式四-->
    <bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
    
  • 步骤3:AppForInstanceUser运行类不用做任何修改,直接运行。


在这里插入图片描述

📚bean的生命周期

⭐️下述内容涉及到的环境配置↓
在这里插入图片描述

  1. 项目中添加BookDao、BookDaoImpl、BookService和BookServiceImpl类。
    public interface BookDao {
        public void save();
    }
    
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ...");
        }
    }
    
    public interface BookService {
        public void save();
    }
    
    public class BookServiceImpl implements BookService{
        private BookDao bookDao;
    
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    
  2. resources下提供spring的配置文件。
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    </beans>
    
  3. 编写AppForLifeCycle运行类,加载Spring的IOC容器,并从中获取对应的bean对象。
    public class AppForLifeCycle {
        public static void main( String[] args ) {
            ApplicationContext ctx = new 
                ClassPathXmlApplicationContext("applicationContext.xml");
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
        }
    }
    

🐇生命周期设置

  • 生命周期:从创建到消亡的完整过程。
  • 在上面这个环境中来为BookDao添加生命周期的控制方法,具体的控制有两个阶段:
    • bean创建之后,想要添加内容,比如用来初始化需要用到资源。
    • bean销毁之前,想要添加内容,比如用来释放用到的资源。
  • 步骤1:添加初始化和销毁方法。在BooDaoImpl类中分别添加两个方法(方法名任意)。
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ...");
        }
        //表示bean初始化对应的操作
        public void init(){
            System.out.println("init...");
        }
        //表示bean销毁前对应的操作
        public void destory(){
            System.out.println("destory...");
        }
    }
    
  • 步骤2:配置生命周期。
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
    
  • 步骤3:AppForLifeCycle.java运行。
    public class AppForLifeCycle {
        public static void main( String[] args ) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
        }
    }
    
  • 运行AppForLifeCycle打印结果为:
    在这里插入图片描述
  • init方法执行了,但是destroy方法却未执行?
    • Spring的IOC容器是运行在JVM中。
    • 运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器获取bean对象,然后调方法执行。
    • main方法执行完后,JVM退出,这个时候IOC容器中的bean还没有来得及销毁就已经结束了,所以没有调用对应的destroy方法。

🐇销毁操作未调用解决方法

  • 方法一】:close()关闭容器

    public class AppForLifeCycle {
        public static void main( String[] args ) {
        	//ApplicationContext中没有close方法,将ApplicationContext更换成ClassPathXmlApplicationContext
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
            //关闭容器(这句话一出现就直接暴力关闭)
            ctx.close();
        }
    }
    

    在这里插入图片描述

  • 方法二】:注册钩子关闭容器,registerShutdownHook()。在容器未关闭之前,提前设置好回调函数,让JVM在退出之前回调此函数来关闭容器。

    public class AppForLifeCycle {
        public static void main( String[] args ) {
        	//registerShutdownHook在ApplicationContext中也没有
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            //注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器(这句代码可以往后放,位置放哪不影响)
            ctx.registerShutdownHook();
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
        }
    }
    

    在这里插入图片描述

  • 👀比较上述两种方法

    • 相同点:这两种都能用来关闭容器。
    • 不同点:close()是在调用的时候关闭,registerShutdownHook()是在JVM退出前调用关闭。

🐇Spring提供的生命周期控制接口

  • Spring提供了两个接口来完成生命周期的控制,好处是可以不用再进行配置init-methoddestroy-method
  • 在BookServiceImpl完成这两个接口的使用:修改BookServiceImpl类,添加两个接口InitializingBeanDisposableBean并实现接口中的两个方法afterPropertiesSetdestroy
    public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
        private BookDao bookDao;
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
        public void save() {
            System.out.println("book service save ...");
            bookDao.save(); 
        }
        public void destroy() throws Exception {
            System.out.println("service destroy");
        }
        public void afterPropertiesSet() throws Exception {
            System.out.println("service init");
        }
    }
    
  • 重新运行AppForLifeCycle类↓
    在这里插入图片描述

⭐️小细节

  • 对于InitializingBean接口中的afterPropertiesSet方法,翻译过来为属性设置之后,对于BookServiceImpl来说,bookDao是它的一个属性,setBookDao方法是Spring的IOC容器为其注入属性的方法。
  • 思考:afterPropertiesSet和setBookDao谁先执行?
    • 验证——在setBookDao方法中添加一句话↓
      public void setBookDao(BookDao bookDao) {
          System.out.println("set .....");
          this.bookDao = bookDao;
      }
      
    • 重新运行AppForLifeCycle,打印结果如下↓
      在这里插入图片描述
    • 所以初始化方法会在类中属性设置之后执行。

⭐️对于bean的生命周期控制在bean的整个生命周期中所处的位置如下
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921019.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全-企业环境渗透2-wordpress任意文件读FFmpeg任意文件读

一、 实验名称 企业环境渗透2 二、 实验目的 【实验描述】 操作机的操作系统是kali 进入系统后默认是命令行界面 输入startx命令即可打开图形界面。 所有需要用到的信息和工具都放在了/home/Hack 目录下。 本实验的任务是通过外网的两个主机通过代理渗透到内网的两个主机。…

Java 对象头、Mark Word、monitor与synchronized关联关系以及synchronized锁优化

1. 对象在内存中的布局分为三块区域&#xff1a; &#xff08;1&#xff09;对象头&#xff08;Mark Word、元数据指针和数组长度&#xff09; 对象头&#xff1a;在32位虚拟机中&#xff0c;1个机器码等于4字节&#xff0c;也就是32bit&#xff0c;在64位虚拟机中&#xff0…

Linux 进程概念与进程状态

目录 1. 冯诺依曼体系结构2. 操作系统&#xff08;Operator System&#xff09;2.1 概念2.2 设计OS的目的2.3 系统调用和库函数概念 3. 进程概念3.1 描述进程 - PCB3.2 task_struct3.3 查看进程3.4 通过系统调用获取进程标识符PID&#xff0c; PPID3.5 通过系统调用创建fork 4.…

计算机网络(14)ip地址超详解

先看图&#xff1a; 注意看第三列蓝色标注的点不会改变&#xff0c;A类地址第一个比特只会是0&#xff0c;B类是10&#xff0c;C类是110&#xff0c;D类是1110&#xff0c;E类是1111. IPv4地址根据其用途和网络规模的不同&#xff0c;分为五个主要类别&#xff08;A、B、C、D、…

shell脚本启动springboot项目

nohup java -jar springboot.jar > springboot.log 2>&1 & 表示日志输出重定向到springboot.log日志文件, 而原本的日志继续输出到 项目同级的log文件夹下, 所以这个重定向没必要. 我们没必要要2分日志 #!/bin/bash# 获取springboot项目的进程ID PID$(ps -e…

51c大模型~合集76

我自己的原文哦~ https://blog.51cto.com/whaosoft/12617524 #诺奖得主哈萨比斯新作登Nature&#xff0c;AlphaQubit解码出更可靠量子计算机 谷歌「Alpha」家族又壮大了&#xff0c;这次瞄准了量子计算领域。 今天凌晨&#xff0c;新晋诺贝尔化学奖得主、DeepMind 创始人哈萨…

FileProvider高版本使用,跨进程传输文件

高版本的android对文件权限的管控抓的很严格,理论上两个应用之间的文件传递现在都应该是用FileProvider去实现,这篇博客来一起了解下它的实现原理。 首先我们要明确一点,FileProvider就是一个ContentProvider,所以需要在AndroidManifest.xml里面对它进行声明: <provideran…

【Java】二叉树:数据海洋中灯塔式结构探秘(上)

个人主页 &#x1f339;&#xff1a;喜欢做梦 二叉树中有一个树&#xff0c;我们可以猜到他和树有关&#xff0c;那我们先了解一下什么是树&#xff0c;在来了解一下二叉树 一&#x1f35d;、树型结构 1&#x1f368;.什么是树型结构&#xff1f; 树是一种非线性的数据结构&…

网口输出的加速度传感器

一、功能概述 1.1 设备简介 本模块为了对电机、风机、水泵等旋转设备进行预测性运维而开发&#xff0c;只需一个模块&#xff0c; 就可以采集旋转设备的 3 路振动信号&#xff08;XYZ 轴&#xff09;和一路温度信号&#xff0c;防护等级 IP67 &#xff0c;能够 适应恶劣的工业…

力扣面试经典 150(上)

文章目录 数组/字符串1. 合并两个有序数组2. 移除元素3. 删除有序数组中的重复项4. 删除有序数组的重复项II5. 多数元素6. 轮转数组7. 买卖股票的最佳时机8. 买卖股票的最佳时机II9. 跳跃游戏10. 跳跃游戏II11. H 指数12. O(1)时间插入、删除和获取随机元素13. 除自身以外数组的…

浅谈 proxy

应用场景 Vue2采用的defineProperty去实现数据绑定&#xff0c;Vue3则改为Proxy&#xff0c;遇到了什么问题&#xff1f; - 在Vue2中不能检测数组和对象的变化 1. 无法检测 对象property 的添加或移除 var vm new Vue({data:{a:1} })// vm.a 是响应式的vm.b 2 // vm.b 是…

P4-1【应用数组进行程序设计】第一节——知识要点:一维数组

视频&#xff1a; P4-1【应用数组进行程序设计】第一节——知识要点&#xff1a;一维数组 项目四 应用数组进行程序设计 任务一&#xff1a;冒泡排序 知识要点&#xff1a;一维数组 目录 一、任务分析 二、必备知识与理论 三、任务实施 一、任务分析 用冒泡法对任意输入…

【数据库入门】关系型数据库入门及SQL语句的编写

1.数据库的类型&#xff1a; 数据库分为网状数据库&#xff0c;层次数据库&#xff0c;关系型数据库和非关系型数据库四种。 目前市场上比较主流的是&#xff1a;关系型数据库和非关系型数据库。 关系型数据库使用结构化查询语句&#xff08;SQL&#xff09;对关系型数据库进行…

day07(单片机高级)继电器模块绘制

目录 继电器模块绘制 原理图 布局 添加板框 布线 按tab修改线宽度 布线换层 泪滴 铺铜 铺铜的作用 铺铜的使用规范 添加丝印 步骤总结 继电器模块绘制 到淘宝找一个继电器模块 继电器模块的使用&#xff08;超详细&#xff09;_继电器模块工作原理-CSDN博客文章浏览阅读4.8w次&…

1+X应急响应(网络)病毒与木马的处置:

病毒与木马的处置&#xff1a; 病毒与木马的简介&#xff1a; 病毒和木马的排查与恢复&#xff1a;

【电路笔记 TMS320F28335DSP】时钟+看门狗+相关寄存器(功能模块使能、时钟频率配置、看门狗配置)

时钟源和主时钟&#xff08;SYSCLKOUT&#xff09; 外部晶振&#xff1a;通常使用外部晶振&#xff08;如 20 MHz&#xff09;作为主要时钟源。内部振荡器&#xff1a;还可以选择内部振荡器&#xff08;INTOSC1 和 INTOSC2&#xff09;&#xff0c;适合无需高精度外部时钟的应…

CCE-基础

背景&#xff1a; 虚拟化产生解决物理机资源浪费问题&#xff0c;云计算出现实现虚拟化资源调度和管理&#xff0c;容器出现继续压榨虚拟化技术产生的资源浪费&#xff0c;用命名空间隔离&#xff08;namespace&#xff09; 灰度升级&#xff08;升级中不影响业务&#xff09…

基于LLama_factory的Qwen2.5大模型的微调笔记

Qwen2.5大模型微调记录 LLama-facrotyQwen2.5 模型下载。huggingface 下载方式Modelscope 下载方式 数据集准备模型微调模型训练模型验证及推理模型导出 部署推理vllm 推理Sglang 推理 LLama-facroty 根据git上步骤安装即可&#xff0c;要求的软硬件都装上。 llama-factory运行…

提取图片高频信息

提取图片高频信息 示例-输入&#xff1a; 示例-输出&#xff1a; 代码实现&#xff1a; import cv2 import numpy as npdef edge_calc(image):src cv2.GaussianBlur(image, (3, 3), 0)ddepth cv2.CV_16Sgray cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)grad_x cv2.Scharr(g…

移动充储机器人“小奥”的多场景应用(上)

一、高速公路服务区应用 在高速公路服务区&#xff0c;新能源汽车的充电需求得到“小奥”机器人的及时响应。该机器人配备有储能电池和自动驾驶技术&#xff0c;能够迅速定位至指定充电点&#xff0c;为待充电的新能源汽车提供服务。得益于“小奥”的机动性&#xff0c;其服务…