【Spring】IoC容器 控制反转 与 DI依赖注入 XML实现版本 第二期

文章目录

  • 基于 XML 配置方式组件管理
  • 前置 准备项目
  • 一、 组件(Bean)信息声明配置(IoC):
    • 1.1 基于无参构造
    • 1.2 基于静态 工厂方法实例化
    • 1.3 基于非静态 工厂方法实例化
  • 二、 组件(Bean)依赖注入配置(DI):
    • 1. 1 基于构造函数的依赖注入(单个构造参数)
    • 1.2 基于构造函数的依赖注入(多构造参数解析)
    • * 1.3 基于Setter方法依赖注入
  • 三、 IoC容器创建和使用:
    • 1. 1 容器实例化
    • 1.2 Bean对象读取
  • 四、 高级特性: 组件(Bean)作用域和周期方法配置:
    • 1. 1 组件周期
    • 1.2 组件作用域
  • 五、 高级特性:FactoryBean特性和使用:
    • 1. 1 FactoryBean简介
    • 1.2 FactoryBean应用
    • 1.3 FactoryBean和BeanFactory区别
  • 六、基于XML方式整合三层架构组件
    • 1.1 需求分析
    • 1.2 项目准备
    • 1.3 配置文件
    • 1.4 测试 数据库 增删改查
    • 1.5 三层结构 搭建 开始
  • 总结
    • XMLIoC方式问题总结 :


基于 XML 配置方式组件管理

前置 准备项目

  • 创建项目工程
  • 导入springioc依赖
    1
    父模块 导入子都需要的依赖,子模块继承:
    pom.xml
    <dependencies>
        <!--spring context依赖-->
        <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.6</version>
        </dependency>
        <!--junit5测试-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.3.1</version>
        </dependency>
    </dependencies>

一、 组件(Bean)信息声明配置(IoC):

1.1 基于无参构造

  1. 创建无参构造 类
  2. 创建spring配置文件
  3. 配置文件中 创建bean

1

-   bean标签:通过配置bean标签告诉IOC容器需要创建对象的组件信息
-   id属性:bean的唯一标识,方便后期获取Bean!
-   class属性:组件类的全限定符!
-   注意:要求当前组件类必须包含无参数构造函数!

1

1.2 基于静态 工厂方法实例化

静态
factory-method: 指定静态工厂方法,注意,该方法必须是static方法。

1.3 基于非静态 工厂方法实例化

1

<!-- 将工厂类进行ioc配置 -->
    <bean id="notStaticMethod" class="com.doug.ClientService"></bean>

<!-- 根据工厂对象的实例工厂方法进行实例化组件对象 -->
    <bean id="clientService" factory-bean="notStaticMethod" factory-method="createInstance"></bean>
  • factory-bean属性:指定当前容器中工厂Bean 的名称。
  • factory-method: 指定实例工厂方法名。注意,实例方法必须是非static的!

二、 组件(Bean)依赖注入配置(DI):

1. 1 基于构造函数的依赖注入(单个构造参数)

1

1.2 基于构造函数的依赖注入(多构造参数解析)

1

-   constructor-arg标签:指定构造参数和对应的值
-   constructor-arg标签:name属性指定参数名、index属性指定参数角标、value属性指定普通属性值

* 1.3 基于Setter方法依赖注入

1

  • property标签: 可以给setter方法对应的属性赋值
  • property 标签: name属性代表set方法标识、ref代表引用bean的标识id、value属性代表基本属性值
    • name 本质是去找方法(set方法),去掉set的

三、 IoC容器创建和使用:

1. 1 容器实例化

读取配置文件,实例化Bean对象

// 方法一:
//参数:String...locations 传入一个或者多个配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean-01.xml","spring-bean-02.xml");
 
 //方法二:
 // 先实例化,再指定配置文件,最后刷新容器触发Bean实例化
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
//设置配置配置文件,方法参数为可变参数,可以设置一个或者多个配置
context.setConfigLocations("spring-bean-01.xml","spring-bean-02.xml");
//后配置的文件,需要调用refresh方法,触发刷新配置
context.refresh();

1.2 Bean对象读取

//方式1: 根据id获取
//没有指定类型,返回为Object,需要类型转化!
HappyComponent happyComponent = 
        (HappyComponent) applicationContext.getBean("bean的id标识");
        
//使用组件对象        
happyComponent.doWork();

//方式2: 根据类型获取
//根据类型获取,但是要求,同类型(当前类,或者之类,或者接口的实现类)只能有一个对象交给IoC容器管理
//配置两个或者以上出现: org.springframework.beans.factory.NoUniqueBeanDefinitionException 问题
HappyComponent happyComponent = applicationContext.getBean(HappyComponent.class);
happyComponent.doWork();

//方式3: 根据id和类型获取 !
// getBean("bean的id标识",class)
HelloComponent helloComponent = applicationContext.getBean("helloComponent", HelloComponent.class);
helloComponent.doWork();

  • 根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:
    • 对象 instanceof 指定的类型』的返回结果,
  • 只要返回的是true就可以认定为和类型匹配,能够获取到。
  • 根据类型获取,同一个类型,在IoC容器中只能有一个bean
  • 存在多个同类型bean 会报错 (见上代码!)
  • IOC的配置一定是实现类,但可以根据接口类型获取值。
    • interfaceA happyComponent = applicationContext.getBean(interfaceA.class);
    • happyComponent.doWork();
    • 根据实现类的父接口 调用它实现类的方法

四、 高级特性: 组件(Bean)作用域和周期方法配置:

1. 1 组件周期

IoC容器实例化和销毁组件对象

  1. 周期方法声明
    1

  2. 周期方法配置bean

<bean id="beanPeriod" class="com.doug.BeanPeriod" init-method="Init" destroy-method="destroy"/>
  1. 测试
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean-01.xml");
        // 正常关闭 , 没调用这个方法,就只执行初始化,然后直接寄(非正常死亡)
        applicationContext.close();

1.2 组件作用域

1
默认就是单例模式,

多例模式:组件对象 getBean 一次就会创建一个组件对象

五、 高级特性:FactoryBean特性和使用:

1. 1 FactoryBean简介

  • BeanFactory IoC容器最大的接口 IoC容器
  • FactoryBean 标准化组件工厂的接口 组件

FactoryBean用于配置复杂的Bean对象,可以将创建过程存储在FactoryBeangetObject方法

FactoryBean<T> 接口提供三种方法:

  • T getObject():

    返回此工厂创建的对象的实例。该返回值会被存储到IoC容器!

  • boolean isSingleton():

    如果此 FactoryBean 返回单例,则返回 true ,否则返回 false 。此方法的默认实现返回 true (注意,lombok插件使用,可能影响效果)。

  • Class<?> getObjectType(): 返回 getObject() 方法返回的对象类型,如果事先不知道类型,则返回 null

1

1.2 FactoryBean应用

FactoryBean使用场景:

  1. 代理类的创建
  2. 第三方框架整合
  3. 复杂对象实例化等
  • 准备FactoryBean的实现类
    1
  • 配置FactoryBean实现类
    <!--
     id -> getObject方法返回的对象标识
     class -> factoryBean标准化工厂类
        -->
    <bean id="javaBean" class="com.doug.ioc02.JavaBeanFactoryBean">
        <property name="value" value="道格维克"/>
    </bean>
  • 测试
    1

1.3 FactoryBean和BeanFactory区别

  • FactoryBean
    • 是 Spring 中一种特殊的 bean,可以在 getObject() 工厂方法自定义的逻辑创建Bean!
    • 是一种能够生产其他 Bean 的 Bean
    • FactoryBean 在容器启动时被创建,而在实际使用时则是通过调用 getObject() 方法来得到其所生产的 Bean
    • FactoryBean 可以自定义任何所需的初始化逻辑,生产出一些定制化的 bean
    • 一般情况下,整合第三方框架,都是通过定义FactoryBean实现
  • BeanFactory
    • Spring 框架的基础,其作为一个顶级接口定义了容器的基本行为
      • 例如管理 bean 的生命周期、配置文件的加载和解析、bean 的装配和依赖注入等
  • BeanFactory 接口提供了访问 bean 的方式

总的来说 , FactoryBean 和 BeanFactory 的区别 :

  • 主要在于FactoryBean 是用于创建 bean 的接口,它提供了更加灵活的初始化定制功能,
  • 而 BeanFactory是用于管理 bean 的框架基础接口,提供了基本的容器功能和 bean 生命周期管理。

六、基于XML方式整合三层架构组件

1.1 需求分析

搭建一个三层架构案例,模拟查询全部学生(学生表)信息,持久层使用JdbcTemplate和Druid技术,使用XML方式进行组件管理!
需求

1.2 项目准备

  • 数据库:
    1
create database studb;

use studb;

CREATE TABLE students (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  gender VARCHAR(10) NOT NULL,
  age INT,
  class VARCHAR(50)
);

INSERT INTO students (id, name, gender, age, class)
VALUES
  (1, '张三', '男', 20, '高中一班'),
  (2, '李四', '男', 19, '高中二班'),
  (3, '王五', '女', 18, '高中一班'),
  (4, '赵六', '女', 20, '高中三班'),
  (5, '刘七', '男', 19, '高中二班'),
  (6, '陈八', '女', 18, '高中一班'),
  (7, '杨九', '男', 20, '高中三班'),
  (8, '吴十', '男', 19, '高中二班');
  • 项目创建:
    spring-ioc-xml-practice-02
  • 依赖导入:
<dependencies>
      <!--spring context依赖-->
      <!--当你引入SpringContext依赖之后,表示将Spring的基础依赖引入了-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>6.0.6</version>
      </dependency>

      <!-- 数据库驱动和连接池-->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.25</version>
      </dependency>

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.8</version>
      </dependency>

      <!-- spring-jdbc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>6.0.6</version>
      </dependency>

</dependencies> 
  • 实体类准备:
package com.doug.ioc;

public class Student {
    private Integer id;
    private String name;
    private String gender;
    private Integer age;
    private String classes;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getClasses() {
        return classes;
    }

    public void setClasses(String classes) {
        this.classes = classes;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", classes='" + classes + '\'' +
                '}';
    }
}

1.3 配置文件

从JAVA写法 改成 bean创建对象
在这里插入图片描述

1.4 测试 数据库 增删改查

    @Test
    public void testForIoC(){
        // 1. 创建IOC容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc01.xml");
        // 2. 获取jdbc组件
        JdbcTemplate jdbcTemplate = applicationContext.getBean(JdbcTemplate.class);
        // 3. 进行数据库的crud操作
        // 3.1 插入 删除 修改 DML update
        String sql = "insert into students(name,gender,age,class) values(?,?,?,?)";
        /*
        * 参数一:sql语句
        * 参数二: 传入占位符?的值 按顺序
        * 返回值:int 影响行数
        * */
        int rows = jdbcTemplate.update(sql, "道格", "男", 25, "十年十班");
        System.out.println(rows);

        // 3.2 查询单条信息
        // 按照 ID 查询一条学生信息 返回实体对象
        sql = "select * from students where id = ?";
        /*
        * 参数一:sql语句
        * 参数二:RowMapper 列名和属性名的映射器接口
        * 参数三:Object...param 占位符 (这里是id数字)
        * 返回值: rowMapper指定的对象  结果返回实体类
        * */
        Student queryStudent = jdbcTemplate.queryForObject(sql, (rs, rowNum) -> {
            // 返回的结果集对象
            // rs 结果集
            // rowNum 行数
            // rs 结果集中获取列的值 赋值给实体类对象即可
            Student student = new Student();
            student.setId(rs.getInt("id"));
            student.setName(rs.getString("name"));
            student.setGender(rs.getString("gender"));
            student.setAge(rs.getInt("age"));
            student.setClasses(rs.getString("class"));
            return student;
        }, 1);
        System.out.println(queryStudent);

        // 3.3 查询所有学生的信息
        sql = "select id,name,gender,age,class as classes from students";
        // BeanPropertyRowMapper 帮助我们自动映射列和属性值!要求列名和属性名一致!不一致需要起别名!
        List<Student> studentList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Student>(Student.class));
        System.out.println(studentList);

结果:
1

1.5 三层结构 搭建 开始

  • dao
    1

  • service

在这里插入图片描述

  • controller

在这里插入图片描述

  • xml 配置文件
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${doug.url}"/>
        <property name="driverClassName" value="${doug.driver}"/>
        <property name="username" value="${doug.username}"/>
        <property name="password" value="${doug.password}"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>

    <bean id="stuDao" class="com.doug.dao.impl.StuDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

    <bean id="stuService" class="com.doug.service.impl.StuServiceImpl">
        <property name="stuDao" ref="stuDao"/>
    </bean>

    <bean id="stuController" class="com.doug.controller.StuController">
        <property name="stuService" ref="stuService"/>
    </bean>
  • 测试
    @Test
    public void testStuControllerMethod(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-02.xml");
        StuController stuController = applicationContext.getBean(StuController.class);
        stuController.findAllStu();
    }

1


总结

lambada
1

XMLIoC方式问题总结 :

  1. 注入的属性必须添加setter方法、代码结构乱!
  2. 配置文件和Java代码分离、编写不是很方便!
  3. XML配置文件解析效率低

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

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

相关文章

Docker vs VM

关于应用程序的托管和开发&#xff0c;市场中的技术和产品琳琅满目。对比 Docker 和 VM&#xff0c;如何取舍&#xff1f;这主要由自身团队的因素决定&#xff0c;在选择 Docker 的情况下&#xff0c;你需要保证程序可在容器和虚拟机中运行。另外&#xff0c;成本和易用性也是重…

前端跨域问题解决,本地代理到域名

1.学习黑马uniapp时遇见的问题: 报跨域错误 但是已经设置了代理&#xff0c;仍然无效。 2.解决&#xff08;多次遇见此问题&#xff0c;特此记录&#xff09;&#xff1a; 最后发现是这里少写了/api&#xff0c;遇见以api开头的接口&#xff0c;则把这些接口转发到target所指向…

32单片机基础:GPIO输出

目录 简介&#xff1a; GPIO输出的八种模式 STM32的GPIO工作方式 GPIO支持4种输入模式&#xff1a; GPIO支持4种输出模式&#xff1a; 浮空输入模式 上拉输入模式 下拉输入模式 模拟输入模式&#xff1a; 开漏输出模式&#xff1a;&#xff08;PMOS无效&#xff0c;就…

详细分析Python中的Pyautogui库(附Demo)

目录 前言1. 基本知识2. 常用方法2.1 通用方法2.2 鼠标操作2.3 消息窗口2.4 截图 前言 该博客主要以入门了解其函数为主&#xff0c;灵活运用&#xff0c;后续会出一些实战结合类&#xff01; 1. 基本知识 PyAutoGUI 是 Python 的一个库&#xff0c;用于实现自动化的图形用户…

信号系统之连续信号处理

1 Delta 函数 连续信号可以分解为缩放和移位的增量函数&#xff0c;就像处理离散信号一样。不同之处在于&#xff0c;连续 delta 函数比其离散函数复杂得多&#xff0c;在数学上也抽象得多。我们不是用它是什么来定义连续 delta 函数&#xff0c;而是用它所具有的特征来定义它…

【眼科大模型】Ophtha-LLaMA2:视觉模型提取图像特征 + LLM基于特征生成眼底病变的诊断报告

Ophtha-LLaMA2&#xff1a;视觉模型提取图像特征 LLM基于特征生成眼底病变的诊断报告 提出背景设计思路选择大模型基座生成诊断报告 论文&#xff1a;https://arxiv.org/pdf/2312.04906.pdf 提出背景 目标是开发一个全面的眼科模型&#xff0c;可以根据不同仪器的检查报告准确…

GitHub | 在 GitHub 上在线展示 Vue 项目

简洁版&#xff1a;上传所有代码 << 构建项目并上传 dist 目录 << 设置仓库 << 访问 Step1&#xff1a;在 GitHub 上新建仓库&#xff0c;并将 Vue 项目的代码 push 到该仓库中。坑点在于&#xff0c;如果你是从 GitHub 上 clone 的别人的项目&#xff0c;那…

vulnhub练习 DC-1复现及分析

一、搭建环境 1.工具 靶机&#xff1a;DC-1 192.168.200.17 攻击机&#xff1a;kali 192.168.200.13 2.注意 攻击机和靶机的网络连接方式要相同&#xff0c;另外DC-1的网络连接方式我这里采用NAT模式&#xff0c;是与kali的网络连接模式相同的&#xff08;当然亦可以选用桥…

国产chat gpt推荐

下述网站响应非常快 会持续更新的! 付费&#xff1a; 小名言 免费&#xff1a; AIchatOS 百度的文心一言

unity学习(32)——跳转到角色选择界面(父子类问题)

新问题 应该是两个脚本之间缺少继承关系 its children 解决起来很简单&#xff0c;把ResceneScript也绑到canvas上就可以了 。 此时&#xff0c;在账号密码正确的情况下&#xff0c;是可以完成场景切换。 对应的代码如下&#xff1a; TMP_Text d GameObject.FindWithTag(&…

板块一 Servlet编程:第五节 Cookie对象全解 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 Servlet编程&#xff1a;第五节 Cookie对象全解 一、什么是CookieCookie的源码 二、Cookie的具体操作&#xff08;1&#xff09;创建Cookie&#xff08;2&#xff09;获取Cookie&#xff08;3&#xff09;设置Cookie的到期时间&#xff08;4&#xff09;设置Cookie的路径…

<网络安全>《42 网络攻防专业课<第八课 - SQL注入漏洞攻击与防范>》

1 SQL注入漏洞利用及防范 1 SQL注入的地位 2 SQL注入的危害及本质 这些危害包括但不局限于&#xff1a; 数据库信息泄漏&#xff1a;数据库中存放的用户的隐私信息的泄露。网页篡改&#xff1a;通过操作数据库对特定网页进行篡改。网站被挂马&#xff0c;传播恶意软件&#…

writing classes ... [xxx of xxxx] 执行时间太长

一、问题展示 二、解决方法 打开设置【File - Settings…】修改堆大小

OpenGL学习——16.多光源

前情提要&#xff1a;本文代码源自Github上的学习文档“LearnOpenGL”&#xff0c;我仅在源码的基础上加上中文注释。本文章不以该学习文档做任何商业盈利活动&#xff0c;一切著作权归原作者所有&#xff0c;本文仅供学习交流&#xff0c;如有侵权&#xff0c;请联系我删除。L…

MySQL 窗口函数温故知新

本文用于复习数据库窗口函数&#xff0c;希望能够温故知新&#xff0c;也希望读到这篇文章的有所收获。 本文以&#xff1a;MySQL为例 参考文档&#xff1a; https://www.begtut.com/mysql/mysql-window-functions.html 使用的样例数据&#xff1a;https://www.begtut.com/m…

Linux|centos7| rust语言的编译开发环境快速部署

前言&#xff1a; rust语言是干什么的&#xff0c;怎么用这些我就不在这里废话了&#xff0c;免得浪费大家的时间&#xff0c;我目前只知道rust音译为铁锈&#xff0c;它的可执行主程序叫cargo&#xff0c;音译为货物 这个语言和python&#xff0c;Java&#xff0c;go等等语言…

每日学习总结20240220

每日总结 20240220 岁月极美&#xff0c;在于它必然的流逝&#xff1b;春花&#xff0c;秋月&#xff0c;夏日&#xff0c;冬雪。 ——三毛 1.svn操作 通过svn创建一个仓库 请写出一套配置 配置文件包括svnserve.conf passwd authz 三个文件 添加用户xiaoming 密码为lx,使得能…

LabVIEW读取excel日期

LabVIEW读取excel日期 | Excel数据表格中有日期列和时间列&#xff0c;如下表所示&#xff1a; 通过LabVIEW直接读取Excel表格数据&#xff0c;读出的日期列和时间列数据与原始表格不一致&#xff0c;直接读出来的数据如下表所示&#xff1a; 日期、时间列数据异常 问题产生原因…

三次握手,四次挥手的大白话版本

三握四挥 首先我们要知道握手和挥手是在做什么&#xff0c;握手是为了让客户端和服务端建立连接&#xff0c;挥手是为了让客户端和服务端断开连接&#xff0c;握手时客户端主动发起请求&#xff0c;挥手双方都能发起请求。 三次握手 有必要解释一下&#xff0c;SYN的意思是同…

OLED示例程序、keil的调试模式

调试方式 串口调试&#xff1a;通过串口通信&#xff0c;将调试信息发送到电脑端&#xff0c;电脑使用串口助手显示调试信息 显示屏调试&#xff1a;直接将显示屏连接到单片机&#xff0c;将调试信息打印在显示屏上 Keil调试模式&#xff1a;借助Keil软件的调试模式&#xf…