四、Spring IoC实践和应用(基于XML配置方式组件管理)

本章概要

  • 基于XML配置方式组件管理
    • 实验一: 组件(Bean)信息声明配置(IoC)
    • 实验二: 组件(Bean)依赖注入配置(DI)
    • 实验三: IoC 容器创建和使用
    • 实验四: 高级特性:组件(Bean)作用域和周期方法配置
    • 实验五: 高级特性:FactoryBean特性和使用
    • 实验六: 基于XML方式整合三层架构组件

4.2 基于XML配置方式组件管理

源码:ssm-spring-part.rar

在这里插入图片描述

4.2.1 实验一: 组件(Bean)信息声明配置(IoC)
4.2.1.1 目标Spring IoC 容器管理一个或多个 bean

这些 Bean 是使用您提供给容器的配置元数据创建的(例如,以 XML 定义的形式)。我们学习,如何通过定义XML配置文件,声明组件类信息,交给 Spring 的 IoC 容器进行组件管理!

4.2.1.2 思路

在这里插入图片描述

4.2.1.3 准备项目
  1. 创建 maven 工程(spring-ioc-xml-01)
  2. 导入 SpringIoC 相关依赖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>
4.2.1.4 基于无参数构造函数

当通过构造函数方法创建一个 bean(组件对象) 时,所有普通类都可以由 Spring 使用并与之兼容。也就是说,正在开发的类不需要实现任何特定的接口或以特定的方式进行编码。只需指定 Bean 类信息就足够了。但是,默认情况下,我们需要一个默认(空)构造函数。

  1. 准备组件类
package com.atguigu.ioc01;
public class HappyComponent {//默认包含无参数构造函数public void doWork() {System.out.println("HappyComponent.doWork");}
}
  1. xml配置文件编写

创建携带spring约束的xml配置文件

在这里插入图片描述

编写配置文件:

文件:resources/spring-bean-01.xml

<!-- 实验一 [重要]创建bean -->
<bean id="happyComponent" class="com.atguigu.ioc01.HappyComponent"/>
  • bean标签:通过配置bean标签告诉IOC容器需要创建对象的组件信息
  • id属性:bean的唯一标识,方便后期获取Bean!
  • class属性:组件类的全限定符!
  • 注意:要求当前组件类必须包含无参数构造函数!
4.2.1.5 基于静态工厂方法实例化除了使用构造函数实例化对象,还有一类是通过工厂模式实例化对象

接下来我们讲解如何定义使用静态工厂方法创建Bean的配置 !

  1. 准备组件类
package com.atguigu.ioc01;
public class ClientService {private static ClientService clientService = new ClientService();private ClientService() {}public static ClientService createInstance() {return clientService;}
}
  1. xml 配置文件编写

文件:resources/spring-bean-01.xml

<bean id="clientService" class="com.atguigu.ioc01.ClientService" factory-method="createInstance"/>
  • class属性:指定工厂类的全限定符!
  • factory-method: 指定静态工厂方法,注意,该方法必须是static方法。
4.2.1.6 基于实例工厂方法实例化

接下来我们讲解下如何定义使用实例工厂方法创建Bean的配置 !

  1. 准备组建类
package com.atguigu.ioc01;public class DefaultServiceLocator {private static ClientServiceImpl clientService = new ClientServiceImpl();public ClientServiceImpl createClientServiceInstance() {return clientService;}
}
package com.atguigu.ioc;
public class ClientServiceImpl {
}
  1. xml 配置文件编写

文件:resources/spring-bean-01.xml

<!-- 将工厂类进行ioc配置 -->
<bean id="serviceLocator" class="com.atguigu.ioc01.DefaultServiceLocator"></bean><!-- 根据工厂对象的实例工厂方法进行实例化组件对象 -->
<bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/>
  • factory-bean 属性:指定当前容器中工厂 Bean 的名称。
  • actory-method: 指定实例工厂方法名。注意,实例方法必须是非static的!
4.2.1.6 图解 IoC 配置流程

在这里插入图片描述

4.2.2 实验二: 组件(Bean)依赖注入配置(DI)
4.2.2.1 目标通过配置文件,实现IoC容器中Bean之间的引用(依赖注入DI配置)。

主要涉及注入场景:基于构造函数的依赖注入和基于 Setter 的依赖注入。

4.2.2.2 思路

在这里插入图片描述

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

基于构造函数的 DI 是通过容器调用具有多个参数的构造函数来完成的,每个参数表示一个依赖项。下面的示例演示一个只能通过构造函数注入进行依赖项注入的类!

  1. 准备组件类
package com.atguigu.ioc02;public class UserDao {
}
package com.atguigu.ioc02;public class UserService {private UserDao userDao;public UserService(UserDao userDao) {this.userDao = userDao;}
}
  1. 编写配置文件

文件:resources/spring-bean-02.xml

<beans><!-- 引用类bean声明 --><bean id="userService" class="com.atguigu.ioc02.UserService"><!-- 构造函数引用 --><constructor-arg ref="userDao"/></bean><!-- 被引用类bean声明 --><bean id="userDao" class="com.atguigu.ioc02.UserDao"/>
</beans>
  • constructor-arg 标签:可以引用构造参数 ref 引用其他 bean 的标识。
4.2.2.4 基于构造函数的依赖注入(多构造参数解析)
  1. 介绍

基于构造函数的 DI 是通过容器调用具有多个参数的构造函数来完成的,每个参数表示一个依赖项。下面的示例演示通过构造函数注入多个参数,参数包含其他bean和基本数据类型!

  1. 准备组件类
package com.atguigu.ioc03;
public class UserDao {
}
package com.atguigu.ioc03;
public class UserService {private UserDao userDao;private int age;private String name;public UserService(int age , String name ,UserDao userDao) {this.userDao = userDao;this.age = age;this.name = name;}
}
  1. 编写配置文件 spring-bean-03.xml
<!-- 场景1: 多参数,可以按照相应构造函数的顺序注入数据 -->
<beans><bean id="userService" class="com.atguigu.ioc03.UserService"><!-- value直接注入基本类型值 --><constructor-arg value="18"/><constructor-arg value="赵伟风"/><constructor-arg ref="userDao"/></bean><!-- 被引用类bean声明 --><bean id="userDao" class="com.atguigu.ioc03.UserDao"/>
</beans>
<!-- 场景2: 多参数,可以按照相应构造函数的名称注入数据 -->
<beans><bean id="userService" class="com.atguigu.ioc03.UserService"><!-- value直接注入基本类型值 --><constructor-arg name="name" value="赵伟风"/><constructor-arg name="userDao" ref="userDao"/><constructor-arg name="age"  value="18"/></bean><!-- 被引用类bean声明 --><bean id="userDao" class="com.atguigu.ioc03.UserDao"/>
</beans>
<!-- 场景2: 多参数,可以按照相应构造函数的角标注入数据 index从0开始 构造函数(0,1,2....)
-->
<beans><bean id="userService" class="com.atguigu.ioc03.UserService"><!-- value直接注入基本类型值 --><constructor-arg index="1" value="赵伟风"/><constructor-arg index="2" ref="userDao"/><constructor-arg index="0" value="18"/></bean><!-- 被引用类bean声明 --><bean id="userDao" class="com.atguigu.ioc03.UserDao"/>
</beans>
  • constructor-arg标签:指定构造参数和对应的值
  • constructor-arg标签:name属性指定参数名、index属性指定参数角标、value属性指定普通属性值
4.2.2.5 基于Setter方法依赖注入
  1. 介绍

开发中,除了构造函数注入(DI)更多的使用的Setter方法进行注入!下面的示例演示一个只能使用纯 setter 注入进行依赖项注入的类。

  1. 准备组件类
package com.atguigu.ioc04;
public class MovieFinder {
}
package com.atguigu.ioc04;public class SimpleMovieLister {private MovieFinder movieFinder;private String movieName;public void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;}public void setMovieName(String movieName) {this.movieName = movieName;}// business logic that actually uses the injected MovieFinder is omitted...
}
  1. 编写配置文件 spring-bean-04.xml
<bean id="simpleMovieLister" class="com.atguigu.ioc04.SimpleMovieLister"><!-- setter方法,注入movieFinder对象的标识idname = 属性名  ref = 引用bean的id值--><property name="movieFinder" ref="movieFinder" /><!-- setter方法,注入基本数据类型movieNamename = 属性名 value= 基本类型值--><property name="movieName" value="消失的她"/>
</bean><bean id="movieFinder" class="com.atguigu.ioc04.MovieFinder"/>
  • property标签: 可以给setter方法对应的属性赋值
  • property 标签: name属性代表set方法标识、ref代表引用bean的标识id、value属性代表基本属性值

总结:

  • 依赖注入(DI)包含引用类型和基本数据类型,同时注入的方式也有多种!主流的注入方式为setter方法注入和构造函数注入,两种注入语法都需要掌握!

特别注意:

  • 引用其他bean,使用ref属性。直接注入基本类型值,使用value属性。
4.2.3 实验三: IoC容器创建和使用
  1. 介绍

上面的实验只是讲解了如何在XML格式的配置文件编写IoC和DI配置!如图:
在这里插入图片描述

想要配置文件中声明组件类信息真正的进行实例化成Bean对象和形成Bean之间的引用关系,我们需要声明IoC容器对象,读取配置文件,实例化组件和关系维护的过程都是在IoC容器中实现的!

  1. 容器实例化
package com.atguigu.ioc05;public class HappyComponent {// 默认包含无参数构造函数public void doWork() {System.out.println("HappyComponent.doWork");}
}

spring-bean-05.xml

<bean id="happyComponent" class="com.atguigu.ioc05.HappyComponent"/>

测试类SpringIocTest.java

package com.atguigu.test;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringIocTest {public void createIoc() {// 方式1:实例化并且指定配置文件// 参数:String...locations 传入一个或者多个配置文件ApplicationContext context = new ClassPathXmlApplicationContext("spring-bean-05.xml");// 方式2:先实例化,再指定配置文件,最后刷新容器触发Bean实例化动作 [springmvc源码和contextLoadListener源码方式]ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext();// 设置配置配置文件,方法参数为可变参数,可以设置一个或者多个配置context1.setConfigLocations("spring-bean-05.xml");// 后配置的文件,需要调用refresh方法,触发刷新配置context1.refresh();}
}
  1. Bean对象读取

测试类SpringIocTest.java

@Test
public void getBeanFromIoc() {//先创建IOC容器对象ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext();applicationContext.setConfigLocations("spring-bean-05.xml");applicationContext.refresh();// 方式1: 根据id获取// 没有指定类型,返回为Object,需要类型转化!HappyComponent happyComponent1 = (HappyComponent) applicationContext.getBean("happyComponent");// 使用组件对象happyComponent1.doWork();// 方式2: 根据类型获取// 根据类型获取,但是要求,同类型(当前类,或者之类,或者接口的实现类)只能有一个对象交给IoC容器管理// 配置两个或者以上出现: org.springframework.beans.factory.NoUniqueBeanDefinitionException 问题HappyComponent happyComponent2 = applicationContext.getBean(HappyComponent.class);happyComponent2.doWork();// 方式3: 根据id和类型获取HappyComponent happyComponent3 = applicationContext.getBean("happyComponent", HappyComponent.class);happyComponent3.doWork();System.out.println(happyComponent1 == happyComponent2);System.out.println(happyComponent2 == happyComponent3);
}

在这里插入图片描述

4.2.4 实验四: 高级特性:组件(Bean)作用域和周期方法配置
4.2.4.1 组件周期方法配置
  1. 周期方法概念

我们可以在组件类中定义方法,然后当IoC容器实例化和销毁组件对象的时候进行调用!这两个方法我们成为生命周期方法!类似于Servlet的init/destroy方法,我们可以在周期方法完成初始化和释放资源等工作。

  1. 周期方法声明
package com.atguigu.ioc06;public class BeanOne {// 周期方法要求: 方法命名随意,但是要求方法必须是 public void 无形参列表public void init() {// 初始化逻辑System.out.println("BeanOne init");}
}
package com.atguigu.ioc06;public class BeanTwo {public void cleanup() {// 释放资源逻辑System.out.println("BeanTwo cleanup");}
}
  1. 周期方法配置 spring-bean-06.xml
<beans><bean id="beanOne" class="com.atguigu.ioc06.BeanOne" init-method="init" /><bean id="beanTwo" class="com.atguigu.ioc06.BeanTwo" destroy-method="cleanup" />
</beans>
  1. 测试
@Test
public void test06(){// 创建iod容器,自动实例化ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-bean-06.xml");// 正常结束ioc容器,自动销毁context.close();
}

在这里插入图片描述

4.2.4.2 组件作用域配置
  1. Bean 作用域概念

<bean 标签声明Bean,只是将Bean的信息配置给SpringIoC容器!在IoC容器中,这些<bean标签对应的信息转成Spring内部 BeanDefinition 对象,BeanDefinition 对象内,包含定义的信息(id,class,属性等等)!
这意味着,BeanDefinition与类概念一样,SpringIoC容器可以可以根据BeanDefinition对象反射创建多个Bean对象实例。
具体创建多少个Bean的实例对象,由Bean的作用域Scope属性指定!

  1. 作用域可选值
取值含义创建对象的时机默认值
singleton在 IOC 容器中,这个 bean 的对象始终为单实例IOC 容器初始化时
prototype这个 bean 在 IOC 容器中有多个实例获取 bean 时

如果是在WebApplicationContext环境下还会有另外两个作用域(但不常用):

取值含义创建对象的时机默认值
request请求范围内有效的实例每次请求
session会话范围内有效的实例每次会话
  1. 作用域配置配置 scope 范围
package com.atguigu.ioc06;public class HappyMachine {private String machineName;public String getMachineName() {return machineName;}public void setMachineName(String machineName) {this.machineName = machineName;}
}
package com.atguigu.ioc06;public class HappyComponent {private String componentName;public String getComponentName() {return componentName;}public void setComponentName(String componentName) {this.componentName = componentName;}
}

spring-bean-06.xml

<!--bean的作用域准备两个引用关系的组件类即可!!-->
<!-- scope属性:取值singleton(默认值),bean在IOC容器中只有一个实例,IOC容器初始化时创建对象 -->
<!-- scope属性:取值prototype,bean在IOC容器中可以有多个实例,getBean()时创建对象 -->
<bean id="happyMachine8" scope="prototype" class="com.atguigu.ioc06.HappyMachine"><property name="machineName" value="happyMachine"/>
</bean><bean id="happyComponent8" scope="singleton" class="com.atguigu.ioc06.HappyComponent"><property name="componentName" value="happyComponent"/>
</bean>
  1. 作用域测试
@Test
public void testExperiment08()  {ApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-bean-06.xml");HappyMachine8 bean = iocContainer.getBean(HappyMachine8.class);HappyMachine8 bean1 = iocContainer.getBean(HappyMachine8.class);//多例对比 falseSystem.out.println(bean == bean1);HappyComponent8 bean2 = iocContainer.getBean(HappyComponent8.class);HappyComponent8 bean3 = iocContainer.getBean(HappyComponent8.class);//单例对比 trueSystem.out.println(bean2 == bean3);
}

在这里插入图片描述

4.2.5 实验五: 高级特性:FactoryBean 特性和使用
4.2.5.1 FactoryBean 简介

FactoryBean 接口是Spring IoC容器实例化逻辑的可插拔性点。用于配置复杂的Bean对象,可以将创建过程存储在FactoryBean 的getObject方法!FactoryBean 接口提供三种方法:

  • T getObject():返回此工厂创建的对象的实例。该返回值会被存储到IoC容器!
  • boolean isSingleton():如果此 FactoryBean 返回单例,则返回 true ,否则返回 false 。此方法的默认实现返回 true (注意,lombok插件使用,可能影响效果)。
  • Class<?> getObjectType(): 返回 getObject() 方法返回的对象类型,如果事先不知道类型,则返回 null 。

在这里插入图片描述

4.2.5.2 FactoryBean 使用场景
  • 代理类的创建
  • 第三方框架整合
  • 复杂对象实例化等
4.2.5.3 Factorybean应用
  1. 准备FactoryBean实现类
package com.atguigu.ioc07;import com.atguigu.ioc06.HappyMachine8;
import org.springframework.beans.factory.FactoryBean;// 实现FactoryBean接口时需要指定泛型
// 泛型类型就是当前工厂要生产的对象的类型
public class HappyFactoryBean implements FactoryBean<HappyMachine8> {private String machineName;public String getMachineName() {return machineName;}public void setMachineName(String machineName) {this.machineName = machineName;}@Overridepublic HappyMachine8 getObject() throws Exception {// 方法内部模拟创建、设置一个对象的复杂过程HappyMachine8 happyMachine = new HappyMachine8();happyMachine.setMachineName(this.machineName);return happyMachine;}@Overridepublic Class<?> getObjectType() {// 返回要生产的对象的类型return HappyMachine8.class;}
}
  1. 配置FactoryBean实现类
<!-- FactoryBean机制 -->
<!-- 这个bean标签中class属性指定的是HappyFactoryBean,但是将来从这里获取的bean是HappyMachine对象 -->
<bean id="happyMachine7" class="com.atguigu.ioc07.HappyFactoryBean"><!-- property标签仍然可以用来通过setXxx()方法给属性赋值 --><property name="machineName" value="iceCreamMachine"/>
</bean>
  1. 测试读取FactoryBean和FactoryBean.getObject对象
@Test
public void testExperiment07() {ApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-bean-07.xml");// 注意: 直接根据声明FactoryBean的id,获取的是getObject方法返回的对象HappyMachine8 happyMachine = iocContainer.getBean("happyMachine7", HappyMachine8.class);System.out.println("happyMachine7 = " + happyMachine);// 如果想要获取FactoryBean对象, 直接在id前添加&符号即可!  &happyMachine7 这是一种固定的约束Object bean = iocContainer.getBean("&happyMachine7");System.out.println("bean = " + bean);
}

在这里插入图片描述

4.2.5.4 FactoryBean 和 BeanFactory 区别

**FactoryBean **是 Spring 中一种特殊的 bean,可以在 getObject() 工厂方法自定义的逻辑创建Bean!是一种能够生产其他 Bean 的 Bean。FactoryBean 在容器启动时被创建,而在实际使用时则是通过调用 getObject() 方法来得到其所生产的 Bean。因此,FactoryBean 可以自定义任何所需的初始化逻辑,生产出一些定制化的 bean。

一般情况下,整合第三方框架,都是通过定义FactoryBean实现!!!

BeanFactory 是 Spring 框架的基础,其作为一个顶级接口定义了容器的基本行为,例如管理 bean 的生命周期、配置文件的加载和解析、bean 的装配和依赖注入等。BeanFactory 接口提供了访问 bean 的方式,例如 getBean() 方法获取指定的 bean 实例。

它可以从不同的来源(例如 Mysql 数据库、XML 文件、Java 配置类等)获取 bean 定义,并将其转换为 bean 实例。同时,BeanFactory 还包含很多子类(例如,ApplicationContext 接口)提供了额外的强大功能。

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

4.2.6 实验六: 基于XML方式整合三层架构组件
4.2.6.1 需求分析

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

在这里插入图片描述

4.2.6.2 数据库准备
CREATE TABLE students (id INT PRIMARY KEY,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, '高中二班');
4.2.6.3 项目准备
  1. 项目创建spring-xml-practice-02
  2. 依赖导入
<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>
  1. 实体类准备
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;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", gender='" + gender + '\'' +", age=" + age +", classes='" + classes + '\'' +'}';}
}
4.2.6.4 JdbcTemplate 技术讲解

为了在特定领域帮助我们简化代码,Spring 封装了很多 『Template』形式的模板类。例如:RedisTemplate、RestTemplate 等等,包括现在要学习的 JdbcTemplate。

jdbc.properties文件,提取数据库连接信息

atguigu.url=jdbc:mysql://localhost:3306/studb
atguigu.driver=com.mysql.cj.jdbc.Driver
atguigu.username=root
atguigu.password=root

spring-ioc.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><!-- 导入外部属性文件 --><context:property-placeholder location="classpath:jdbc.properties" /><!-- 配置数据源 --><bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${atguigu.url}"/><property name="driverClassName" value="${atguigu.driver}"/><property name="username" value="${atguigu.username}"/><property name="password" value="${atguigu.password}"/></bean><!-- 配置 JdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!-- 装配数据源 --><property name="dataSource" ref="druidDataSource"/></bean></beans>

基于jdbcTemplate的CRUD使用

public class JdbcTemplateTest {/*** 使用jdbcTemplate进行DML动作*/@Testpublic void testDML() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc.xml");JdbcTemplate jdbcTemplate = applicationContext.getBean(JdbcTemplate.class);// TODO 执行插入一条学员数据String sql = "insert into students (id,name,gender,age,class) values (?,?,?,?,?);";/*参数1: sql语句参数2: 可变参数,占位符的值*/int rows = jdbcTemplate.update(sql, 9, "十一", "男", 18, "二年三班");System.out.println("rows = " + rows);}/*** 查询单条实体对象* public class Student {* private Integer id;* private String name;* private String gender;* private Integer age;* private String classes;*/@Testpublic void testDQLForPojo() {String sql = "select id , name , age , gender , class as classes from students where id = ? ;";ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc.xml");JdbcTemplate jdbcTemplate = applicationContext.getBean(JdbcTemplate.class);// 根据id查询Student student = jdbcTemplate.queryForObject(sql, (rs, rowNum) -> {// 自己处理结果映射Student stu = new Student();stu.setId(rs.getInt("id"));stu.setName(rs.getString("name"));stu.setAge(rs.getInt("age"));stu.setGender(rs.getString("gender"));stu.setClasses(rs.getString("classes"));return stu;}, 2);System.out.println("student = " + student);}/*** 查询实体类集合*/@Testpublic void testDQLForListPojo() {String sql = "select id , name , age , gender , class as classes from students  ;";ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc.xml");JdbcTemplate jdbcTemplate = applicationContext.getBean(JdbcTemplate.class);/*query可以返回集合!BeanPropertyRowMapper就是封装好RowMapper的实现,要求属性名和列名相同即可*/List<Student> studentList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));System.out.println("studentList = " + studentList);}}

在这里插入图片描述

4.2.6.5 三层架构搭建和实现
  1. 持久层
import com.atguigu.domain.Student;
import java.util.List;// 接口
public interface StudentDao {/*** 查询全部学生数据** @return*/List<Student> queryAll();
}
import com.atguigu.dao.StudentDao;
import com.atguigu.domain.Student;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;import java.util.List;// 实现类
public class StudentDaoImpl implements StudentDao {private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}/*** 查询全部学生数据** @return*/@Overridepublic List<Student> queryAll() {String sql = "select id , name , age , gender , class as classes from students ;";/*query可以返回集合!BeanPropertyRowMapper就是封装好RowMapper的实现,要求属性名和列名相同即可*/List<Student> studentList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));return studentList;}
}
  1. 业务层
import com.atguigu.domain.Student;import java.util.List;// 接口
public interface StudentService {/*** 查询全部学员业务** @return*/List<Student> findAll();}
import com.atguigu.dao.StudentDao;
import com.atguigu.domain.Student;
import com.atguigu.service.StudentService;import java.util.List;// 实现类
public class StudentServiceImpl implements StudentService {private StudentDao studentDao;public void setStudentDao(StudentDao studentDao) {this.studentDao = studentDao;}/*** 查询全部学员业务** @return*/@Overridepublic List<Student> findAll() {List<Student> studentList = studentDao.queryAll();return studentList;}
}
  1. 表述层
import com.atguigu.domain.Student;
import com.atguigu.service.StudentService;import java.util.List;public class StudentController {private StudentService studentService;public void setStudentService(StudentService studentService) {this.studentService = studentService;}public void findAll() {List<Student> studentList = studentService.findAll();System.out.println("studentList = " + studentList);}
}
4.2.6.6 三层架构 IoC 配置

spring-ioc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><!-- 导入外部属性文件 --><context:property-placeholder location="classpath:jdbc.properties" /><!-- 配置数据源 --><bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${atguigu.url}"/><property name="driverClassName" value="${atguigu.driver}"/><property name="username" value="${atguigu.username}"/><property name="password" value="${atguigu.password}"/></bean><!-- 配置 JdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!-- 装配数据源 --><property name="dataSource" ref="druidDataSource"/></bean><bean id="studentDao" class="com.atguigu.dao.impl.StudentDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate" /></bean><bean id="studentService" class="com.atguigu.service.impl.StudentServiceImpl"><property name="studentDao" ref="studentDao" /></bean><bean id="studentController" class="com.atguigu.controller.StudentController"><property name="studentService" ref="studentService" /></bean></beans>
4.2.6.7 运行测试
import com.atguigu.controller.StudentController;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class ControllerTest {@Testpublic void testRun() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc.xml");StudentController studentController = applicationContext.getBean(StudentController.class);studentController.findAll();}
}

在这里插入图片描述

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

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

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

相关文章

自助借还办证一体机软件需求说明书

1. 简介 1.1 项目概括 本项目主要实现读者自助办证、借书、还书、查询、续借的功能&#xff0c;减轻管理员的工作量&#xff0c;提升读者的借阅体验&#xff0c;提高了图书的借阅量与流通率&#xff0c;是图书馆智能化、无人化建设的重要步骤。 1.2 项目背景 ​ 目前各大图…

WEB渗透—PHP反序列化(四)

Web渗透—PHP反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩…

使用 React 实现自定义数据展示日历组件

目录 背景实现日历组件父组件数据 效果最后 背景 项目中需要实现一个日历组件&#xff0c;并且需要展示月&#xff0c;日所对应的数据&#xff08;因为项目需求问题&#xff0c;就不统计年数据总量&#xff09;。网上找了一堆&#xff0c;基本都不大符合项目需求&#xff0c;且…

OpenHarmony鸿蒙原生应用开发,ArkTS、ArkUI学习踩坑学习笔记,持续更新中。

一、AMD处理器win10系统下&#xff0c;DevEco Studio模拟器启动失败解决办法。 结论&#xff1a;在BIOS里面将Hyper-V打开&#xff0c;DevEco Studio模拟器可以成功启动。 二、ArkTS自定义组件导出、引用实现。 如果在另外的文件中引用组件&#xff0c;需要使用export关键字导…

3ds max软件中的一些常用功能分享!

3ds max软件有很多小伙伴反馈说&#xff0c;明明有很多3ds max教程资料。却不知道如何入门3dmax。 掌握3dmax基本功能是开始使用3dmax的基础之一&#xff0c;所以&#xff0c;小编带大家盘点一下3dmax常用操作。 3dmax常用功能介绍如下&#xff0c;快快跟着小编一起看起来。 1…

预测性维护在汽车制造行业中的应用

汽车制造行业是一个高度复杂和精细化的领域&#xff0c;依赖于各种设备来完成生产流程。这些设备包括机械装配线、焊接机器人、喷涂设备、传送带等。然而&#xff0c;这些设备在长时间运行中不可避免地会遇到各种故障&#xff0c;给生产进程带来延误和成本增加。为了应对这一挑…

LeetCode Hot100 79.单词搜索

题目&#xff1a; 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Button按钮组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Button按钮组件 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、Button按钮组件 Button 组件也是基础组件之一&#xff0c;和其它基础组件不…

Linux之grep、sed、awk

目录 1.grep 2.sed 3.awk 1.grep grep 擅长过滤查找&#xff0c;按行进行过滤 例&#xff1a; 当有用户对我们的主机进行爆破攻击时&#xff0c;我们可以使用grep将 ip 查找出来&#xff0c;进行封锁等处理 在 /var/log 目录下的 secure 文件中存放在用户登录连接信息&am…

自动化测试成本高效果差,意义在哪?

自动化测试的成本高效果差&#xff1f;首先这个结论就太过武断了一些。 任何技术都需要放到适合的地方去使用&#xff0c;否则一定是达不到理想的效果的。举例大炮打蚊子&#xff0c;同样是成本高效果差&#xff0c;难道大炮就没有存在的意义了吗&#xff1f; 当然不是&#…

ATKXCOM串口助手接受中文字符乱码问题

中文乱码大多是编码格式问题&#xff0c;如心知天气API返回的数据编码格式为UTF-8格式&#xff0c;同理串口调试助手需要更改为对应的编码格式&#xff0c;正点原子的串口调试助手具有多种编码格式可以更改。 PS:点击左下角设置图标即可设置

OpenAI发布AGI安全风险框架!董事会可随时叫停GPT-5等模型发布,奥特曼也得乖乖听话

OpenAI 再次强调模型安全性&#xff01;AGI 安全团队 Preparedness 发布模型安全评估与监控框架&#xff01; 这两天关注 AI 圈新闻的小伙伴们可能也有发现&#xff0c;近期的 OpenAI 可谓进行了一系列动作反复强调模型的“安全性”。 前有 OpenAI 安全系统&#xff08;Safety…

工业镜头常见的类型

在机器视觉中&#xff0c;工业镜头作为机器视觉系统的核心部件&#xff0c;常常需要和工业相机搭配使用。工业镜头&#xff0c;属于一种光学系统。光学系统是指由透镜、反射镜、棱镜和光阑等多种光学元件按一定次序组合成的系统。那么工业镜头都有哪些类型&#xff1f; 一、按照…

搭建APP应用程序如何选择服务器

Hello&#xff0c;各位同学们好&#xff01;我是咕噜铁蛋&#xff0c;我经常收到许多关于如何搭建APP的询问。其中&#xff0c;如何选择服务器是许多初创企业和开发者经常面临的问题。带着这些问题我也通过一些科技手段收集整理了些知识&#xff0c;今天我就和大家来来探讨如何…

BKP 备份寄存器 RTC 实时时钟-stm32入门

这一章节我们要讲的主要内容是 RTC 实时时钟&#xff0c;对应手册&#xff0c;是第 16 章的位置。 实时时钟这个东西&#xff0c;本质上是一个定时器&#xff0c;但是这个定时器&#xff0c;是专门用来产生年月日时分秒&#xff0c;这种日期和时间信息的。所以学会了 STM32 的…

HTML + JavaScript 实现网页录制音频与下载

HTML JavaScript 实现网页录制音频与下载 HTML JavaScript 实现网页录制音频与下载简介getUserMediaMediaRecorder获取和处理音频流实现音频的录制和播放音频效果的处理实时语音通话的应用兼容性和 Latency 问题 项目代码运行实例参考源码下载 HTML JavaScript 实现网页录制…

银行测试:第三方支付平台业务流,功能/性能/安全测试方法

1、第三方支付平台的功能和结构特点 在信用方面&#xff0c;第三方支付平台作为中介&#xff0c;在网上交易的商家和消费者之间作一个信用的中转&#xff0c;通过改造支付流程来约束双方的行为&#xff0c;从而在一定程度上缓解彼此对双方信用的猜疑&#xff0c;增加对网上购物…

【lesson18】MySQL内置函数(1)日期函数和字符串函数

文章目录 日期函数函数使用具体使用案例建表插入数据建表插入数据 字符串函数函数使用具体使用案例建表插入数据测试 日期函数 函数使用 获得年月日&#xff1a; 获得时分秒&#xff1a; 获得时间戳&#xff1a; 获得现在的时间&#xff1a; 在日期的基础上加日期&#xf…

C++ Qt开发:TableWidget表格组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍TableWidget表格组件的常用方法及灵活运用。 …

基于python的leetcode算法介绍之递归

文章目录 零 算法介绍一 简单示例 辗转相除法Leetcode例题与思路[509. 斐波那契数](https://leetcode.cn/problems/fibonacci-number/)解题思路&#xff1a;题解&#xff1a; [206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/)解题思路&#xff1a;题解&…