当前位置: 首页 > news >正文

基于XML的自动装配~

基于XML的自动装配之场景模拟:

自动装配根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类类型或者接口类型赋值

之前我们学过的依赖注入,我们在为不同属性赋值时,例如类类型的属性,我们使用的是ref为其赋值,而字面量我们使用的是value,而对于类类型来说,我们只需要找到IOC容器中所对应的bean的对象,通过ref属性来引用该bean所对应的id,我们就把该bean所对应的对象来为类类型的属性或者接口类型的属性赋值,那么自动装配使得我们不再需要通过书写property去指定某一个属性,再通过当前的ref去引用某一个id了,我们设置了自动装配之后,那么当前这个bean所有的类类型的属性都可以找到所匹配的bean来自动为当前属性赋值。

那么下面我们就来进行一个场景的模拟:其包含三层架构包括:控制层、业务层、持久层

在这里插入图片描述

创建完成之后,通过代码来处理他们之间的关系:

第一步:在UserController中创建service对象:

public class UserController {private UserService userService=new UserServiceImpl();}

上述这种方式是我们没有学习IOC之前的写法,它的缺点在于,功能不是单一且一成不变的,若此后service接口有新的实现类,或者是我们想对当前类进行更新和维护,如果我们还是上述这种写法,那么只能在原有的代码上进行修改,以便于扩展新的实现类等,修改代码之后,代码需要重新编译,打包等,这样才能呈现出我们修改之后的效果

但学习了IOC之后,我们知道IOC是用来管理对象和对象之间的依赖关系,那么我们就可以将UserController交给IOC容器管理,UserServiceImpl,UserDaoImpl也是可以交给IOC容器管理的,注意,这里说的是接口的实现类,并不是接口,因为我们设置一个bean标签,它的class只能是一个类,而不能是一个接口

将这三个组件交给IOC容器管理之后,那么就可以在UserController中设置Userservice的成员变量,并且设置该成员变量的set和get方法,由于我们将UserController交给IOC容器管理,那么Userservice就会被动的接受IOC容器的注入,也就是说我们可以通过set为当前的接口赋值,现在Userservice的实现类是UserServiceImpl,那么此后如果有新的实现类,我们只需要在配置文件中,将其id修改为新的实现类的id即可

其正确写法如下所示:

package Controller;import Service.UserService;public class UserController {private UserService userService ;public UserService getUserService() {return userService;}public void setUserService(UserService userService) {this.userService = userService;}
}

第二步:处理UserServiceImpl类

package Service.impl;import Service.UserService;
import dao.UserDao;public class UserServiceImpl  implements UserService {//设置Dao并为其设置set和get方法或者设置有参构造,因为当我们将对象交给IOC容器管理之后,我们要想对其进行赋值,要么使用set注入,要么是构造器注入public UserDao userDao;public UserDao getUserDao() {return userDao;}public void setUserDao(UserDao userDao) {this.userDao = userDao;}
}

假设我们在Controller类中加入下述方法,模拟实现调用userservice中的save方法来处理业务逻辑:

public void save(){userService.save();
}

但此时save方法在UserService接口并不存在啊,因此我们需要在UserService 接口中去创建该方法 ,如下所示:

 //保存用户信息void save();

由于UserServiceImpl实现了UserService接口,那么需要对其方法进行实现,通过userDao去调用,如下所示在UserServiceImpl中添加下述代码:

@Overridepublic void save() {userDao.save();}

同样的UserDao中并没有该方法,因此我们也需要在该接口中去创建该方法,如下所示在UserDao中添加下述代码:

 void save();

由于UserDaoImpl实现了UserDao接口,因此也需要实现该方法,将该方法重写如下所示:

@Overridepublic void save() {System.out.println("保存成功");}

下面就可以将其三层架构以及之间的逻辑关系交给IOC容器管理:

三层架构的三个组件交给IOC容器管理,其实并不仅仅是将这三个组件交给IOC容器管理,还将它们之间的依赖关系交给IOC容器管理

在resources下创建,spring-autowrie-xml.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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 注意:这里bean标签中的class一定是一个类,而不是接口,接口类型的这里一定写的是其实现类--><!-- 控制层中来调用service处理业务逻辑--><bean id="UserController" class="Controller.UserController"><property name="userService" ref="userService"></property></bean><!--service中调用Dao实现持久化操作--><bean id="userService" class="Service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean><bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
</beans>

编写测试类

import Controller.UserController;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class autowireTest {@Testpublic void test(){ApplicationContext ioc=new ClassPathXmlApplicationContext("spring-autowrie-xml.xml");UserController userController=ioc.getBean(UserController.class);userController.save();}
}

输出如下所示:

保存成功

基于XML的自动装配之byType:

上面的场景模拟中,我们依然是通过property标签手动的配置,但当我们设置了自动装配之后,就不需要通过property标签手动赋值, 只要配置自动装配,它就可以自动在IOC容器中找到某一个bean ,自动为当前属性赋值,但需要注意的是,它只针对于类类型或者接口类型,而如果是字面量类型的属性,是不可以的

既然如此,自动装配使得我们免于书写property标签,那么我们是否可以将其property标签删除呢?

在这里插入图片描述

测试结果如下:

编译器报了一个空指针异常,由于我们上述的操作是将赋值的代码块注释了,此时的bean标签中的 Controller的UserService就是默认值,即为null

在这里插入图片描述

由此接下来,我们将学习如何配置自动装配:

在这里插入图片描述

修改spring-autowrie-xml.xml文件中的bean标签

通过设置autowire的值为byType,相当于设置了自动装配,当前的bean对象可通过要赋值属性的值,在IOC中匹配某个bean,为属性赋值

<bean id="UserController" class="Controller.UserController" autowire="byType"></bean>
<bean id="userService" class="Service.impl.UserServiceImpl" autowire="byType"></bean>
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>

测试依然成功:

在这里插入图片描述

但如果我们在当前的IOC容器一个bean都无法匹配到呢?

修改spring-autowrie-xml.xml文件,使其只保留一个bean对象,测试结果如下:

依然是出现空指针异常,也就说明了当我们把autowire属性的值设置为byType时,如果能够匹配到bean,那么就为其赋值,否则就使用默认值

在这里插入图片描述

如下所示,如果当在一个IOC容器中同时能够匹配到两个bean时,未测试之前,编译器都报错,

 <bean id="UserController" class="Controller.UserController" autowire="byType"></bean><bean id="userService" class="Service.impl.UserServiceImpl" autowire="byType"></bean>
<bean id="Service" class="Service.impl.UserServiceImpl" autowire="byType"></bean><bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="Dao" class="dao.impl.UserDaoImpl"></bean>

在这里插入图片描述

测试结果如下:

当通过类型找到了多个类型匹配的bean,会抛出NoUniqueBeanDefinitionException[没有唯一的bean被匹配]异常

在这里插入图片描述

当使用byType实现自动装配时,IOC容器中有且只有一个类型的bean能够为属性赋值

基于XML的自动装配之byName:

byName:把当前要赋值的属性的属性名作为id,在IOC容器中去匹配到对应的bean,来为当前属性赋值,如下所示:

在这里插入图片描述

一般情况下,我们并不会使用这种方式,由于之前我们提到,一个类型对应的bean,我们不需要在IOC容器中配置多次,所以我们根据byType即可,但如果说byType无法满足,那么就说明子IOC容器中,我们包含的类型有多个bean,那么我们就可以通过byName来实现,只要有一个bean的id和我们要赋值的属性的属性名一致,那么我们就可以指定对应的bean为当前的属性赋值

如下所示,当我们将其匹配方式都修改为byName,此时即使在一个IOC容器中,同一个类有多个bean,也不会产生任何的报错,因为通过byName我们一定是能够匹配到一个具体的bean为当前属性赋值的

在这里插入图片描述

我们再次进行测试,依然可以测试成功!

在这里插入图片描述

在byType存在没有匹配到任何一个bean的情况,同样的在这里也会出现,如下所示,我们将其属性修改为一个不存在的:

在这里插入图片描述

再次进行测试:

产生空指针异常

在这里插入图片描述

既然存在一个都没匹配到, 也就会存在同时匹配到多个的情况,如下所示:

在这里插入图片描述

先别急着运行, 我们修改的是其id,那么什么是id呢?id是唯一标识,其值是不能重复的,我们将两个bean对象的id修改为一样的值之后,这已经不是是否能够自动装配成功的问题了,而是IOC容器我们都无法成功获取,它已经是解析文件错误的问题了

测试结果如下所示:

在这里插入图片描述

相关文章:

基于XML的自动装配~

基于XML的自动装配之场景模拟&#xff1a; 自动装配&#xff1a;根据指定的策略&#xff0c;在IOC容器中匹配某一个bean&#xff0c;自动为指定的bean中所依赖的类类型或者接口类型赋值 之前我们学过的依赖注入&#xff0c;我们在为不同属性赋值时&#xff0c;例如类类型的属性…...

完全二叉树的4种遍历方式

一张二叉树的图 1&#xff0c;二叉树的特点 每个点p的左儿子是p*2,右儿子是p*21&#xff0c;可以分别表示为p<<1与p<<1|1节点的序号是从左到右&#xff0c;从上到下增加的每个点至多2个儿子&#xff08;屁话&#xff08;bushi&#xff09;&#xff09; 2&#xff…...

【vue2】使用elementUI进行表单验证实操(附源码)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;vue使用elementUI进行表单验证实操&#xff08;附源码&#xff09; 【前言】我们在构建一…...

JUC之阻塞队列解读(BlockingQueue)

目录 BlockingQueue 简介 BlockingQueue 核心方法 1.放入数据 2.获取数据 入门代码案例 常见的 BlockingQueue ArrayBlockingQueue(常用) LinkedBlockingQueue(常用) PriorityBlockingQueue SynchronousQueue LinkedTransferQueue LinkedBlockingDeque 小结 Bloc…...

LCHub:ChatGPT4和低代码来临,程序员面临下岗?

一个网友吐槽道: “ 建站出来了,你们说程序员会失业。 低代码出来了,你们说程序员会失业。 Copilot出来了,你们说程序员会失业。 Chatgpt出来了,你们说程序员会失业 虽然这只是网友的吐槽,但却引起了小编的好奇。为何程序员那么容易被新技术取代?今天小编打算跟大家…...

【Node.js】Express框架的基本使用

✍️ 作者简介: 前端新手学习中。 &#x1f482; 作者主页: 作者主页查看更多前端教学 &#x1f393; 专栏分享&#xff1a;css重难点教学 Node.js教学 从头开始学习 目录 初识Express Express简介 什么是Express 进一步理解 Express Express能做什么 Express的基本使用 …...

使用docker 和 kubnernetes 部署单节点/多节点 kafka 环境

参考资料 https://kafka.apachecn.org/documentation.html#configuration kafka的broker有三个核心配置 broker.idlog.dirszookeeper.connect docker启动单节点kafka环境 启动zookeeper 可配置的环境变量&#xff0c;https://gallery.ecr.aws/bitnami/zookeeper $ docker …...

Linux使用:环境变量指南和CPU和GPU利用情况查看

Linux使用&#xff1a;环境变量指南和CPU和GPU利用情况查看Linux环境变量初始化与对应文件的生效顺序Linux的变量种类设置环境变量直接运行export命令定义变量修改系统环境变量修改用户环境变量修改环境变量配置文件环境配置文件的区别profile、 bashrc、.bash_profile、 .bash…...

深入浅出 SSL/CA 证书及其相关证书文件(pem、crt、cer、key、csr)

互联网是虚拟的&#xff0c;通过互联网我们无法正确获取对方真实身份。数字证书是网络世界中的身份证&#xff0c;数字证书为实现双方安全通信提供了电子认证。数字证书中含有密钥对所有者的识别信息&#xff0c;通过验证识别信息的真伪实现对证书持有者身份的认证。数字证书可…...

Compose(1/N) - 概念 基本使用

一、概念 1.1 解决的问题 APP展示的数据绝大多数不是静态数据而是会实时更新&#xff0c;传统的命令式UI写法更新界面繁琐且容易同步错误。1.2 Compose优势 由一个个可组合的Composable函数&#xff08;可看作是一个Layout布局&#xff09;拼成界面&#xff0c;方便维护和复用…...

2023高质量Java面试题集锦:高级Java工程师面试八股汇总

人人都想进大厂&#xff0c;当然我也不例外。早在春招的时候我就有向某某某大厂投岗了不少简历&#xff0c;可惜了&#xff0c;疫情期间都是远程面试&#xff0c;加上那时自身也有问题&#xff0c;导致屡投屡败。突然也意识到自己肚子里没啥货&#xff0c;问个啥都是卡卡卡卡&a…...

MySQL多表查询 子查询效率(DQL语句)

多表关系 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种&#xff1a; 一对多(多…...

Linux中 ps命令详解

一、基础概念 指令&#xff1a; ps 作用&#xff1a;查看系统进程&#xff0c;比如正在运行的进程有哪些&#xff0c;什么时候开始运行的&#xff0c;哪个用户运行的&#xff0c;占用了多少资源。 参数&#xff1a; -e 显示所有进程-f 显示所有字段&#xff08;UID&…...

【Python语言基础】——Python 关键字

Python语言基础——Python 关键字 文章目录Python语言基础——Python 关键字一、Python 关键字一、Python 关键字 Python 有一组关键字&#xff0c;这些关键字是保留字&#xff0c;不能用作变量名、函数名或任何其他标识符&#xff1a; 关键字 描述 and 逻辑运算符。 as 创建别…...

Java SE 基础(8)关键字和保留字

关键字 定义&#xff1a;被Java 语言赋予了特殊含义&#xff0c;用做专门用途的字符串&#xff08;单词&#xff09; 特点&#xff1a; 关键字中所有字母都为小写 用于定义数据类型的关键字 class、interface、 enum 、byte 、short、 int 、long、 float、 double、 char 、…...

Thinkphp 6.0响应输出和重定向

本节课我们来学习一下响应操作&#xff0c;响应输出和重定向。 一&#xff0e;响应操作 1. 响应输出&#xff0c;有好几种&#xff1a;包括 return、json()和 view()等等&#xff1b; 2. 默认输出方式是以 html 格式输出&#xff0c;如果你发起 json 请求&#xff0c;则输出 js…...

Centos html 中文 显示为乱码

0 &#xff1a; CentOS发布静态网页 之 httpd开启 https://blog.csdn.net/weixin_39689870/article/details/118146160 #yum install -y httpd #systemctl start httpd.service/etc/httpd/conf&#xff1a;该目录存放Apache服务器的配置文件 /var/www/html&#xff1a;该目录是…...

Helm学习笔记

文章目录概念定义helm组件helm的工作流程helm安装helm仓库helm部署应用helm应用的更新或回退或卸载概念 定义 学习helm首先得了解helm是什么&#xff0c;我们先来看一下helm的定义&#xff1a;helm是将kubernetes的各种资源对象打包&#xff0c;类似于Linux中的yum工具&#…...

深入学习JavaScript系列(二)——作用域和作用域链

本篇为第二篇&#xff0c;本系列文章会在后续学习后持续更新。 第一篇&#xff1a;#深入学习JavaScript系列&#xff08;一&#xff09;—— ES6中的JS执行上下文 第二篇&#xff1a;# 深入学习JavaScript系列&#xff08;二&#xff09;——作用域和作用域链 第三篇&#x…...

【计算机视觉 | 目标检测】DETR风格的目标检测框架解读

文章目录一、前言二、理解2.1 DETR的理解2.2 DETR的细致理解2.2.1 Backbone2.2.2 Transformer encoder2.2.3 Transformer decoder2.2.4 Prediction feed-forward networks (FFNs)2.2.5 Auxiliary decoding losses2.3 更具体的结构2.4 编码器的原理和作用2.5 解码器的原理和作用…...

【LeetCode】剑指 Offer 41. 数据流中的中位数 p214 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof 1. 题目介绍&#xff08;41. 数据流中的中位数&#xff09; 如何得到一个数据流中的中位数&#xff1f;如果从数据流中读出奇数个数值&#xff0c;那么中位数就是所有数值排序之后位…...

CSS3 知识总结

1&#xff0c;什么是CSS 用于定义网页的样式&#xff0c;包括不同设备和屏幕尺寸的设计、布局和显示变化。 2&#xff0c;CSS的作用优点 CSS 描述 HTML 元素如何在屏幕、纸张或其他媒体上显示 CSS 节省了大量工作。它可以一次控制多个网页的布局 3&#xff0c;css构成 CSS 规…...

回溯算法37:解数独

主要是我自己刷题的一些记录过程。如果有错可以指出哦&#xff0c;大家一起进步。 转载代码随想录 原文链接&#xff1a; 代码随想录 leetcode链接&#xff1a;37. 解数独 题目&#xff1a; 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则…...

【蓝桥杯-筑基篇】动态规划

&#x1f353;系列专栏:蓝桥杯 &#x1f349;个人主页:个人主页 目录 1.最大连续子段和 2.LCS 最大公共子序列 3.LIS 最长上升子序列 4.数塔 5.最大子矩阵和 6.背包问题 ①01背包问题 ②完全背包 1.最大连续子段和 这段代码是一个求最大子数组和的算法&#xff0c;使用…...

Unity利用Photon PUN2框架快速实现多人在线游戏实例分享

简介 Photon 是一个泛用性的 ScoketServer 套装软件,可用于多人在线游戏、聊天室、大厅游戏,并同时支持 Windows、Unity3D、iOS、Android、Flash 等平台。Photon 包含两个部分,一部分是 Socket 服务器,另一部分是其针对各个平台编写的 SDK,Unity3D 平台对应的 SDK 为 Pho…...

ChatGPT直出1.5w字论文查重率才30% - 基于物联网技术的智能家居控制系统设计与实现

文章目录ChatGPT直出1.5w字论文查重率才30% - 基于物联网技术的智能家居控制系统设计与实现一、绪论1.1 研究背景与意义1.2 国内外研究现状分析1.3 研究内容与目标1.4 研究方向和思路二、物联网技术与智能家居概述2.1 物联网技术原理与应用2.2 智能家居的概念与发展历程2.3 智能…...

特斯拉的操作系统是用什么语言编写的?

总目录链接>> AutoSAR入门和实战系列总目录 文章目录特斯拉车辆操作系统特斯拉GitHub中使用的语言Ruby和GoPythonSwift 和 Objective CQt我们知道操作系统至少需要一些非常低级的代码&#xff0c;这些代码在系统首次启动时运行&#xff0c;必须使用接近硬件的语言编写。…...

C++学习8-C++提高编程

文章目录前言一、模板1.1 模板的概念1.2 函数模板1.2.1 函数模板语法1.2.2 函数模板注意事项1.2.3 函数模板案例复习&#xff1a;计算数组长度1.2.4 普通函数与函数模板的区别1.2.5 普通函数与函数模板的调用规则1.2.6 模板的局限性1.3 类模板1.3.1 类模板语法1.3.2 类模板与函…...

ubuntu安装git server

一安装 要在Ubuntu上安装Git服务器,需要按照以下步骤进行操作: 安装Git: sudo apt-get update sudo apt-get install git 创建一个Git用户和一个Git仓库目录: sudo adduser git sudo mkdir /home/git/repo.git sudo chown git:git /home/git/repo.git 初始化Git仓库: c…...

物流云数据分析平台

物流云数据分析服务平台 http://project.webcats.cn/bx/36569/2455/index.html 本次系统模拟的是湖南省数据&#xff0c;解释权归杭氏集团所有&#xff01; 1、系统简介: 物流大数据集成展示系统旨在通过大屏幕全面显示指定地区的物流运营车辆、物流公司和货主的相关信息和…...