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

news2025/2/28 21:50:19

文章目录

  • 基于 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配置文件解析效率低

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【经验分享】分类算法与聚类算法有什么区别?白话讲解

经常有人会提到这个问题&#xff0c;从我个人的观点和经验来说2者最明显的特征是&#xff1a;分类是有具体分类的数量&#xff0c;而聚类是没有固定的分类数量。 你可以想象一下&#xff0c;分类算法就像是给你一堆水果&#xff0c;然后告诉你苹果、香蕉、橙子分别应该放在哪里…

MKS射频RF电源Elite系列匹配器MW-2513功能电源操作使用说明中文

MKS射频RF电源Elite系列匹配器MW-2513功能电源操作使用说明中文

代码随想录算法训练营第二十三天 | 669. 修剪二叉搜索树,108.将有序数组转换为二叉搜索树,538.把二叉搜索树转换为累加树 [二叉树篇]

代码随想录算法训练营第二十三天 LeetCode 669. 修剪二叉搜索树题目描述思路递归参考代码 LeetCode 108.将有序数组转换为二叉搜索树题目描述思路参考代码 LeetCode 538.把二叉搜索树转换为累加树题目描述思路参考代码 LeetCode 669. 修剪二叉搜索树 题目链接&#xff1a;669. …

认识K8S

K8S K8S 的全称为 Kubernetes (K12345678S) 是一个跨主机容器编排工具 作用 用于自动部署、扩展和管理“容器化&#xff08;containerized&#xff09;应用程序”的开源系统。 可以理解成 K8S 是负责自动化运维管理多个容器化程序&#xff08;比如 Docker&#xff09;的集群…

Android Studio基础(下载安装与简单使用)

1、搭建Android开发平台 1.1 Android Studio 下载地址及版本说明 Android 开发者官网&#xff1a; https://developer.android.com/index.html&#xff08;全球&#xff0c;需科学上网&#xff09; https://developer.android.google.cn/index.html&#xff08;国内&#xff…

【Java程序员面试专栏 数据结构】三 高频面试算法题:栈和队列

一轮的算法训练完成后,对相关的题目有了一个初步理解了,接下来进行专题训练,以下这些题目就是汇总的高频题目,因为栈和队列这两哥们结构特性比较向对应,所以放到一篇Blog中集中练习 题目题干直接给出对应博客链接,这里只给出简单思路、代码实现、复杂度分析 题目关键字…

详解AT24CXX驱动开发(linux platform tree - i2c应用)

目录 概述 1 认识AT24Cxx 1.1 AT24CXX的特性 1.2 AT24CXX描述 1.2.1 引脚 1.2.2 容量描述 1.2.3 设备地址 1.3 操作时序 1.3.1 写单个字节时序 1.3.2 写page字节时序 1.3.3 读取当前数据时序 1.3.4 随机读取数据 1.3.5 连续读取多个数据 2 驱动开发 2.1 硬件接口…

小清新卡通人物404错误页面源码

小清新卡通人物404错误页面源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 蓝奏云&#xff1a;https://wfr.lanzout.com/i6XbU1olftde

发电机项目 2/19

MQTT 一.MQTT是什么&#xff1f; MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布/订阅&#xff08;publish/subscribe&#xff09;模式的“轻量级”通讯协议&#xff0c;该协议构建于TCP/IP协议…

【Python】OpenCV-图片添加水印处理

图片添加水印处理 1. 引言 图像处理中的水印添加是一种常见的操作&#xff0c;用于在图片上叠加一些信息或标识。本文将介绍如何使用OpenCV库在图片上添加水印&#xff0c;并通过详细的代码注释来解释每一步的操作。 2. 代码示例 以下是一个使用OpenCV库的简单代码示例&…

2023年全球前端大技术大会(GMTC北京站2023):核心内容与学习收获(附大会核心PPT下载)

此次峰会是一次内容丰富、有深度和广度的技术盛会。参会者不仅可以了解前端技术的最新发展和未来趋势&#xff0c;还可以与业界专家交流心得&#xff0c;提升自己的技能和能力。同时&#xff0c;此次大会也促进了全球前端社区的交流和合作&#xff0c;推动了前端技术的创新和发…

仪表板展示|DataEase看中国:历年研究生报考数据分析

背景介绍 在信息时代的浪潮中&#xff0c;研究生教育作为培养高层次专业人才的重要通道&#xff0c;不断吸引着广大毕业生和在职人士的关注。今天我们结合2018年&#xff5e;2024年的研究生报考数据&#xff0c;以数字为镜&#xff0c;深入了解近年来研究生培养态势。 本文将…

爬虫在网页抓取的过程中可能会遇到哪些问题?

在网页抓取&#xff08;爬虫&#xff09;过程中&#xff0c;开发者可能会遇到多种问题&#xff0c;以下是一些常见问题及其解决方案&#xff1a; 1. IP封锁&#xff1a; 问题&#xff1a;封IP是最常见的问题&#xff0c;抓取的目标网站会识别并封锁频繁请求的IP地址。 解决方案…

C#开发AGV地图编辑软件

C#自己开发AGV地图编辑软件&#xff1a; 1、自由添加和删除站点、停车位、小车、运行路径。 2、编辑得地图以XML文件保存。 3、导入编辑好地图的XML文件。 4、程序都是源码&#xff0c;可以直接在此基础上进行二次开发。 下载链接&#xff1a;https://download.csdn.net/d…

Linux:sed进阶(12)

Linux&#xff1a;shell脚本&#xff1a;基础使用&#xff08;5&#xff09;《正则表达式-sed工具》_linux脚本表达式s-CSDN博客https://blog.csdn.net/w14768855/article/details/132347574?ops_request_misc%257B%2522request%255Fid%2522%253A%252217084222871680019707523…

普中51单片机学习(定时器和计数器)

定时器和计数器 51单片机有两组定时器/计数器&#xff0c;因为既可以定时&#xff0c;又可以计数&#xff0c;故称之为定时器/计数器。定时器/计数器和单片机的CPU是相互独立的。定时器/计数器工作的过程是自动完成的&#xff0c;不需要CPU的参与。51单片机中的定时器/计数器是…

nginx的功能以及运用

nginx与apache的对比 nginx优点 nginx使用场景 编译安装nginx过程 1.先清空opt文件夹 2.关闭防火墙&#xff0c;关闭防护 3 安装依赖包&#xff0c;可以通过本地yum去安装 首先就是挂载&#xff0c;随后切换到配置文件中修改 4本地配置文件配置内容 5 随后安装环境包 yum -y …

【大厂AI课学习笔记】【2.2机器学习开发任务实例】(9)模型优化

模型训练后&#xff0c;就要进行模型优化了。 一般来讲&#xff0c;很简单&#xff0c;优化就是不换模型换参数&#xff0c;或者直接换模型。 换了之后来对比&#xff0c;最后选个最好的。 比如在本案例中&#xff0c;选择LinearRegression后&#xff0c;MSE从22下降到12&am…

LWM(LargeWorldModel)大世界模型-可文字可图片可视频-多模态LargeWorld-详细安装记录

说明 Large World Model&#xff08;LWM&#xff09;是一个通用的大环境多模态自回归模型&#xff0c;它利用了一个技术名为RingAttention&#xff0c;通过在大型的多样化视频和图书数据集上的训练&#xff0c;实现了对语言、图像和视频的理解与生成能力。 在github上已有4.2k…

医疗在线问诊小程序:开启数字化医疗新篇章

随着科技的飞速发展&#xff0c;医疗行业正逐步向数字化转型。其中&#xff0c;医疗在线问诊小程序作为一种新型的医疗健康服务模式&#xff0c;为人们提供了更为便捷、高效的医疗咨询服务。本文将探讨医疗在线问诊小程序的发展背景、优势及应用场景&#xff0c;以期为医疗行业…