SSM框架学习记录-Spring_day01

2023-11-06

1.核心概念


当前项目中的问题

下面代码的实现十分简单,但是业务层需要调用数据层的方法,就要在业务层new数据层的对象,如果数据层的实现类发生变化,业务层的代码也需要跟着改变,意味着要编译打包和重新部署


// 数据层实现
public class FoodDaoImpl implements FoodDao{
    public void save(){
        ...
    }
}
// 业务层实现
public class FoodServiceImpl implements FoodService{
    private FoodDao fd = new FoodDaoImpl();
    public void save(){
        fd.save();
    }
} 

IOC、IOC容器、Bean、DI*

针对上述问题,Spring提出了一个解决方案:使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象(Spring的核心概念)


IOC(Inversion of Control)
  • 什么是控制反转IOC?使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部
  • SpringIOC之间的关系是什么?
    • Spring技术对IOC思想进行了实现
    • Spring提供了一个容器(即IOC容器),用来充当IOC思想中的外部
  • IOC容器的作用以及内部存放的是什么?
    • IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象
    • 被创建或被管理的对象在IOC容器中统称为Bean
  • IOC容器中创建好servicedao对象后,程序能正确执行么?不行!service运行需要依赖dao对象,IOC容器中虽然有servicedao对象,但service对象和dao对象没有任何关系,需要将二者进行绑定
DI(Dependency Injection)

上述提到需要绑定对象间的关系,使用的就是DI


  • 什么是依赖注入DI?在容器中建立beanbean之间的依赖关系的整个过程称为依赖注入

  • IOC容器中哪些bean之间要建立依赖关系?如业务层需要依赖数据层,service就要和dao建立依赖关系

目标

充分解耦:

  • 使用IOC容器管理bean
  • IOC容器内将有依赖关系的bean进行关系绑定
  • 使用对象时不仅可以直接从IOC容器中获取,并且获取到的bean已经绑定了所有的依赖关系

2.入门案例


IOC入门


思路分析

  1. Spring是使用容器来管理bean对象的,管什么?主要管理项目中所使用到的类对象,比如ServiceDao
  2. 如何将被管理的对象告知IOC容器?使用配置文件
  3. 被管理的对象交给IOC容器,要想从容器中获取对象先要获取IOC容器,如何获取?Spring框架提供相应的接口
  4. IOC容器得到后,如何从容器中获取bean?调用Spring框架提供对应接口中的方法
代码实现

参考Spring_01_quickstart


DI入门

分为思路和代码


思路分析

  1. 要想实现依赖注入,必须要基于IOC管理bean
  2. Service中使用new形式创建的Dao对象是否保留?删除,因为要使用IOC容器中的bean对象
  3. Service中需要的Dao对象如何进入到Service中?在Service中提供方法(set方法),让IOC容器可以通过该方法传入bean对象
  4. ServiceDao间的关系如何描述?使用配置文件
代码实现

参考Spring_01_quickstart


3.IOC相关内容


bean基础配置

主要掌握:

  • bean标签的idclass属性的使用
  • 对于是否设置单例的思考

代码参考Spring_02_base_config


  • idbeanid,在容器中唯一

  • classbean的类型(即bean的全路径类名),注意不能使用接口(因为接口无法创建对象)

  • name:定义bean的别名,存在多个就使用,;或者空格分隔,之后在refgetBean方法中中也可以使用别名

  • scope:定义bean的作用范围,singleton表示单例(默认),prototype表示非单例

    • 为什么bean默认为单例?避免了对象的频繁创建与销毁,性能高

    • bean在容器中是单例的,会不会产生线程安全问题?

      • 如果对象是有状态对象(即该对象有成员变量可以用来存储数据的),所以会存在线程安全问题
      • 如果对象是无状态对象(即该对象没有成员变量没有进行数据存储),因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题
    • 哪些bean对象适合交给容器进行管理?

      • 表现层对象
      • 业务层对象
      • 数据层对象
      • 工具对象
    • 哪些bean对象不适合交给容器进行管理?

      • 封装实例的域对象,因为会引发线程安全问题

bean实例化

主要掌握:

  • bean是如何创建的?
  • 实例化bean的三种方式

代码参考Spring_03_bean_instance


  • bean如何创建?使用反射,因为把构造方法设置为私有也可以使用bean,所以使用的是反射

  • 实例化bean的三种方式:

    • 构造方法实例化:调用的是无参构造方法,因为把无参构造方法删除,并且设置一个有参构造方法,运行时会报错
    <bean id="bookDao" class="com.psj.dao.impl.BookDaoImpl"/>
    
    • 静态工厂实例化(了解即可):
    <bean id="orderDao" class="com.psj.factory.OrderDaoFactory" factory-method="getOrderDao"/>
    
    • 实例工厂实例化(了解即可):和静态工厂的区别在于工厂中的方法一个是静态一个不是,并且配置也不同

      <bean id="userFactory" class="com.psj.factory.UserDaoFactory"/>
      <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
      
      • FactoryBean的使用:上述配置过于复杂,因为factory-method名称不固定每次都要配置,并且还需要特意创建id=userFactorybean配合使用
      // FactoryBean创建对象
      public class UserDaoFactoryBean implements FactoryBean<UserDao> {
          // 代替原始实例工厂中创建对象的方法(相当于统一了方法名为getObject)
          public UserDao getObject() throws Exception {
              return new UserDaoImpl();
          }
      
          public Class<?> getObjectType() {
              return UserDao.class;
          }
          
          // 如果要设置为单例/非单例,还可以实现isSingleton方法(不实现就取默认值-单例)
      }
      
      <bean id="userDao" class="com.psj.factory.UserDaoFactoryBean"/>
      

bean的生命周期

bean生命周期指bean对象从创建到销毁的整体过程;bean生命周期控制指在bean创建后到销毁前做的事

主要掌握:

  • 生命周期设置
  • bean的生命周期

代码参考Spring_04_bean_lifecycle


  • 生命周期设置:

    • 添加初始化和销毁方法:分为不实现接口和实现接口两种
      • BooDaoImpl类中分别添加两个方法,方法名任意,
      • BookServiceImpl类中实现两个接口InitializingBeanDisposableBean,并实现接口中的方法afterPropertiesSetdestroy
    • 配置生命周期:对于不实现接口和实现接口两个情况,配置生命周期方式也不同
      • 不实现接口的方式需要在配置文件添加配置init-methoddestroy-method
      • 实现接口的方式则无需添加上述方法
  • 关闭容器(了解即可,因为交给Tomcat容器管理):不关闭容器无法执行消耗方法,关闭方式分为直接使用close方法和先注册钩子再使用close方法

  • bean的生命周期:

    • 初始化容器:
      1. 创建对象(内存分配)
      2. 执行构造方法
      3. 执行属性注入(set操作)
      4. 执行bean初始化方法
    • 使用bean:
      1. 执行业务操作
    • 关闭/销毁容器:
      1. 执行bean销毁方法

4.DI相关内容


依赖注入的两种方式

主要掌握:

  • setter注入
  • 构造器注入
  • 两个方式的使用选择

代码参考Spring_05_di_setSpring_06_di_constructor


  • setter注入:

    • 引用类型:详情见代码BookServiceImpl.javaapplicationContext.xml

    • 基本数据类型:和引用类型的区别在于applicationContext.xml中将ref改为value

    <bean id="bookDao" class="com.psj.dao.impl.BookDaoImpl">
        <property name="connectionNum" value="100"/>
        <property name="databaseName" value="mysql"/>
    </bean>
    
  • 构造器注入:在实体类中添加有参构造器,主要修改在于applicationContext.xml

  • 引用类型:详情见代码中的applicationContext.xml,对于构造方法中形参名称和类型重复的问题也有说明

  • 基本数据类型:和引用类型的区别在于applicationContext.xml中将ref改为value

  • 使用选择:

    • 强制依赖(指对象在创建的过程中必须要注入指定的参数)使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
    • 可选依赖(指对象在创建过程中注入的参数可有可无)使用setter注入进行,灵活性强
    • Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
    • 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
    • 如果受控对象没有提供setter方法就必须使用构造器注入,自己开发的模块推荐使用setter注入

自动装配

IOC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配

主要掌握:

  • 自动装配的方式
  • 注意事项

代码参考Spring_07_di_autoware


  • 自动装配方式:

    <bean id="bookService" class="com.psj.service.impl.BookServiceImpl" autowire="xxx"/>
    
    • 按类型(常用):autowire="byType"
    • 按名称:autowire="byName",需要保证被依赖的beanid名和类中setter方法中把set删除并将首字母大写后的名称一致
    • 按构造方法
    • 不启用自动装配
  • 注意事项:

    • 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
    • 类中需要实现setter方法
    • 只能对引用类型依赖注入,不能对基本数据类型操作

集合注入

前面完成的是引用类型和基本数据类型的注入,还有集合类型(既可装基本数据类型也可装引用数据类型)未说明

主要掌握:

  • 不同集合类型的注入

代码参考Spring_08_di_collection


  • 不同集合类型的注入:详情见applicationContext.xml

    • property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写<array>、<list>、<set>、<map>、<props>标签
    • List的底层也是通过数组实现的,所以<list><array>标签可混用
    • 集合中要添加引用类型,把<value>标签改成<ref>标签即可
    <property name="array">
        <array>
            <ref bean="xxx">
        </array>
    </property>
    

参考


https://www.bilibili.com/video/BV1Fi4y1S7ix?p=1-16

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SSM框架学习记录-Spring_day01 的相关文章

随机推荐

  • quartz对于定时任务Misfire的处理

    使用quartz过程中 产生了很多问题 遇到就记录一下 虽然用的比较少了 但还是有一些项目在使用 问题描述 创建一个每天执行的任务test1 创建自动运行状态 然后停止任务 一直等到当天定时时间过去 然后再启动 发现定时任务还是先执行了一次
  • 在Bios中开启虚拟化设置

    1 进入BIOS 开机时按baiF2或F12或DEL或ESC等键 各电脑有所不同 2 进入duBIOS后 找到Configuration选项 选zhi择Intel Virtual Technology并回车 将光标dao移至Enabled
  • C++使用模板实现元素的反序

    实现任意类型序列中元素的反序 所涉知识点 示例代码 开发环境 运行结果 注意 所涉知识点 阅读此文需要掌握的知识点 回调函数 模板类 类模板 栈 示例代码 这里直接上代码 pragma once include
  • Qt中的并发

    QThread是一个低级 low level 类 适合用于显式地构建长期运行的线程 QtConcurrent是一个命名空间 提供了用于编写并发软件的更高层次的类和算法 该命名空间中有一个重要的类 QThreadPool 这是一个管理线程池的
  • [第四届-强网杯]:Funhash

  • C#的基本知识

    1 static修饰符 本页介绍 static 修饰符关键字 static 关键字也是 using static 指令的一部分 使用 static 修饰符可声明属于类型本身而不是属于特定对象的静态成员 static 修饰符可用于声明 sta
  • Spring中事务几个常见的问题

    首先 事务这个概念是数据库层面的 Spring只是基于数据库中的事务进行扩展 以及提供了一些能让程序员更新方便操作事务的方式 Spring如何处理事务 Spring中支持编程式事务和声明式事务管理两种方式 1 编程式事务 可以使用Trans
  • 一天内Boss转发5k次,「高性能Java:核心原理案例实战」已被封杀

    前言 市面上讲Java框架的书很多 包括SpingBoot SpringCloud Kafka等 但这些书通常只会让你技术的 量 增长 而 质 仍处于SSM的阶段 而且互联网上并没有体系化 结构化的提升技术的 质 的教材 于是团长行动了起来
  • ubuntu环境下编译内核详解

    一 下载源代码和编译软件的准备 下载内核源代码 http www kernel org 注意 点击2 6 25内核的F版 即完整版 如果你懒得去网站点联接 运行下列命令 代码 cd wget http www kernel org pub
  • c语言代码中调用系统命令行.sh shell脚本,linux shell system传参

    C语言代码中调用命令行 1 使用system 命令行 执行完命令行后 会返回原先C代码的位置 继续执行 2 如果命令行中需要传参 使用 sprintf 先处理好命令行的内容 再 system system echo 123 int a 3
  • C/C++基本数据类型所占字节数

    关于这个基本的问题 很早以前就很清楚了 C标准中并没有具体给出规定那个基本类型应该是多少字节数 而且这个也与机器 OS 编译器有关 比如同样是在32bits的操作系统系 VC 的编译器下int类型为占4个字节 而tuborC下则是2个字节
  • 文件的结构及存取方法

    文件的组织形式是文件的结构 从不同的角度分析文件有不同的结构形式 逻辑结构和物理结构 从用户角度出发 研究文件的抽象组织方式而定义的文件组织形式为文件的逻辑结构 从系统的角度出发 研究文件的物理组织方式而定义的文件组织形式为文件的物理结构
  • 【虚拟机】VMware16保姆级安装教程

    大家好 我是雷工 工作中需要用到各种各样的工控软件 有时候甚至需要不同版本的软件 但频繁装卸软件比较麻烦 而且像WinCC和博图软件对系统要求比较严格 卸载重装可能就出问题 此时就不得不重装系统 重装系统各种软件都需要重装一遍 费时费力 这
  • 七、Python基础(异常、模块、文件操作)

    七 Python基础 异常 模块 文件操作 目录 七 Python基础 异常 模块 文件操作 一 异常 1 抛出异常 2 简单的捕获异常语法 3 错误类型的捕获 4 异常捕获的完整语法 5 异常的传递 6 raise 主动抛出异常 二 模块
  • 关于面向对象中的get 和set方法的总结,为什么不用public的详解,详解。

    我们都知道去构造一个实体类的时候 标准都是去 private 一个私有变量 然后再给这个私有 变量加上 公开 get 和 set 我总是会忍不住去想一下 为什么不直接去public 变量 是为了什么 是一种标准 还是说有什么好处 发现网上确
  • 行为驱动开发(BDD)你准备好了吗?

    GitChat 作者 冰尘 原文 行为驱动开发 BDD 你准备好了吗 关注微信公众号 GitChat 技术杂谈 一本正经的讲技术 不要错过文末彩蛋 这个Chat笔者将会和大家一起探讨下面的主题 什么是行为驱动开发 BDD 为什么使用行为驱动
  • STM32+ESP8266(ESP-12F)物联网温度计-移植paho MQTT协议连接阿里云

    STM32 ESP8266 ESP 12F 物联网温度计 移植paho MQTT协议连接阿里云 目录 STM32 ESP8266 ESP 12F 物联网温度计 移植paho MQTT协议连接阿里云 一 硬件及软件准备 1 硬件 STM32单
  • stm32串口通信,收发字符串,并对其进行解析

    串口以字符串接收和发送 将传输的数据转化为整数 正负 stm32发送端 motor position Read Encoder Angle Encoder sensor position Get Adc Average Angle Adc
  • Java后端WebSocket的Tomcat实现

    一 WebSocket简单介绍 随着互联网的发展 传统的HTTP协议已经很难满足Web应用日益复杂的需求了 近年来 随着HTML5的诞生 WebSocket协议被提出 它实现了浏览器与服务器的全双工通信 扩展了浏览器与服务端的通信功能 使服
  • SSM框架学习记录-Spring_day01

    1 核心概念 当前项目中的问题 下面代码的实现十分简单 但是业务层需要调用数据层的方法 就要在业务层new数据层的对象 如果数据层的实现类发生变化 业务层的代码也需要跟着改变 意味着要编译打包和重新部署 数据层实现 public class