Spring实现IoC:依赖注入/构造注入

● 控制反转,反转的是什么?
○ 将对象的创建权利交出去,交给第三方容器负责。
○ 将对象和对象之间关系的维护权交出去,交给第三方容器负责。
● 控制反转这种思想如何实现呢?
○ DI(Dependency Injection):依赖注入

依赖注入

依赖注入:
● 依赖指的是对象和对象之间的关联关系。
● 注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。
依赖注入常见的实现方式包括两种:
● 第一种:set注入
● 第二种:构造注入

在第一个程序中,尽管通过Spring容器创建并管理了一个对象,但以第一章为例,表现层创建了一个Userservice控制层对象:

private Userservice userService = new UserServiceImp();

而在第二章中

   ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");Object userBean = applicationContext.getBean("userDaoBean");//这两行代码完成了"new UserServiceImp"的功能,还剩另一半功能,即将容器创建的对象赋值给任意层的对象,将这个具体的张三放到工作岗位上,这另一半就是依赖注入.

set注入

set注入,基于set方法实现的,底层会通过反射机制调用属性对应的set方法然后给属性赋值。这种方式要求属性必须对外提供set方法。

新建模块:spring6-002-dependency-injection
本例中,方便起见,不再采用接口-实现类的方式,而是每一层直接定义一个抽象类.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.powernode</groupId><artifactId>spring6-002-dependency-injection</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><repositories><repository><id>repository.spring.milestone</id><name>Spring Milestone Repository</name><url>https://repo.spring.io/milestone</url></repository></repositories><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.0-M2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j2-impl</artifactId><version>2.19.0</version></dependency></dependencies><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties></project>

结构
在这里插入图片描述

resources-spring.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"><!--       提前规划好本次项目是2层_持久层&&控制层,并且每层是一个类,等一下直接去创建对应的包,类--><bean id="userDaoBean" class="com.sunsplanter.spring6.dao.UserDao"/><bean id="userServiceBean" class="com.sunsplanter.spring6.service.UserService">
<!--  set哪个对象(注入哪个对象),就在spring.xml中找到对应管理该对象的标签,在bean标签中增加一个<property>子标签该子标签的name属性必须满足规范:去掉该set方法的set,剩下单词采用驼峰命名法,即mySySQLUserDao该子标签的ref属性,指定要注入的bean的id此处,在控制层利用spring容器创建了持久层UserDao对象,而后自定义了一个setMySQLUserDao的set方法进行注入且注入的是持久层对象UserDao,因此ref处填userDaoBean实现原理:
通过property标签获取到set方法:setMySQLUserDao()
通过反射机制调用setMySQLUserDao()方法给属性赋值
property标签的name是提示set方法名。
property标签的ref是要注入的bean对象的id。
(通过ref属性来完成bean的装配,这是bean最简单的一种装配方式。装配指的是:创建系统组件之间关联的动作)--><property name="mySQLUserDao" ref="userDaoBean"/></bean></beans>
package com.sunsplanter.spring6.dao;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class UserDao {//log4j2可以选择输出到控制台/文件,还可以选择各种输出等级private static final Logger logger = LoggerFactory.getLogger(UserDao.class);public void insert(){logger.info("saving...");}
}
package com.sunsplanter.spring6.service;import com.sunsplanter.spring6.dao.UserDao;public class UserService {
//创建一个持久层对象,但这次不再依赖调用下层创建,而是用Spring容器创建,并且用Set依赖注入的方法进行赋值private UserDao userDao;
////ALT+insert用Idea生成set方法
//    public void setUserDao(UserDao userDao) {
//        this.userDao = userDao;
//    }//自定义set方法//要求1:必须是set开始//要求2:set哪个对象(注入哪个对象),就在spring.xml中找到对应管理该对象的标签,在bean标签中增加一个<property>子标签//该子标签的name属性必须满足规范:去掉该set方法的set,剩下单词采用驼峰命名法,即mySySQLUserDaopublic void setMySQLUserDao(UserDao xyz){this.userDao = xyz;}public void saveuser(){userDao.insert();}
}
package com.sunsplanter.spring6.test;import com.sunsplanter.spring6.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringDITest {@Testpublic void testSetDI(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");UserService userService = applicationContext.getBean("userServiceBean", UserService.class);userService.saveuser();}
}

总结:set注入的核心实现原理:通过反射机制调用set方法来给属性赋值,让两个对象之间产生关系。


构造注入

核心原理:通过调用构造方法来给属性赋值。
与依赖注入的核心区别:构造注入是在对象实例化的过程中注入的.

结构为:
在这里插入图片描述
其中,Userservice,spring_dependency.xml,SpringDITest_dependency不再使用

package com.sunsplanter.spring6.service;import com.sunsplanter.spring6.dao.UserDao;
import com.sunsplanter.spring6.dao.VipDao;public class CustomerService {//先声明两个持久层的对象,然后利用spring容器构造出后,用构造方法注入private UserDao userDao;private VipDao vipDao;public CustomerService(UserDao userDao, VipDao vipDao) {//按照先后顺序,对应spring2_constructor第三个bean中0号和1号constructor标签this.userDao = userDao;this.vipDao = vipDao;}public void saveUsers(){userDao.insert();vipDao.insert();}
}
<?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 id="userDaoBean" class = "com.sunsplanter.spring6.dao.UserDao"/><bean id="vipDaoBean" class = "com.sunsplanter.spring6.dao.VipDao"/><bean id="customerServiceBean" class = "com.sunsplanter.spring6.service.CustomerService">
<!--        构造注入的标签的第一种方法
index属性指定参数下标,序号从0开始,对应着CustomerService的构造方法中的两个先后对象
ref属性指定要注入的bean的id-->
<!--        <constructor-arg index = "0" ref="userDaoBean"/>-->
<!--        <constructor-arg index = "1" ref="vipDaoBean"/>--><!--        构造注入的标签的第二种方法
index属性指定参数下标,序号从0开始,对应着CustomerService的构造方法中的两个先后参数(即对象名)--><constructor-arg name = "userDao" ref="userDaoBean"/><constructor-arg name = "vipDao" ref="vipDaoBean"/></bean></beans>
package com.sunsplanter.spring6.test;import com.sunsplanter.spring6.service.CustomerService;
import com.sunsplanter.spring6.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringDITest_constructor {@Testpublic void testConstructorDI(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring2_constructor.xml");CustomerService custormerService = applicationContext.getBean("customerServiceBean", CustomerService.class);custormerService.saveUsers();}
}

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

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

相关文章

Linux telnet命令

Linux telnet命令用于远端登入。 执行telnet指令开启终端机阶段作业&#xff0c;并登入远端主机。 语法 telnet [-8acdEfFKLrx][-b<主机别名>][-e<脱离字符>][-k<域名>][-l<用户名称>][-n<记录文件>][-S<服务类型>][-X<认证形态>…

Eureka工作原理

Eureka的工作原理 Eureka是Netflix开发的一个服务发现框架&#xff0c;它主要用于AWS云环境中&#xff0c;用于构建可伸缩的微服务架构。Eureka主要由两个组件构成&#xff1a;Eureka Server和Eureka Client。下面详细介绍它们的工作原理。 Eureka Server Eureka Server提供服…

【开题报告】基于SpringBoot的校园投诉系统的设计与实现

1.选题背景 校园管理是学校日常运行的重要组成部分&#xff0c;随着社会的发展和学生数量的增加&#xff0c;校园内的问题和纠纷也逐渐增多。例如&#xff0c;学生可能遇到与教师或其他学生之间的矛盾、设施维护问题、课程安排冲突等。这些问题如果得不到及时解决&#xff0c;…

【损失函数】Cross Entropy Loss 交叉熵损失

1、介绍 主页介绍的几种损失函数都是适用于回归问题损失函数&#xff0c;对于分类问题&#xff0c;最常用的损失函数是交叉熵损失函数 Cross Entropy Loss。它用于测量两个概率分布之间的差异&#xff0c;通常用于评估分类模型的性能。 2、公式 对于二分类问题&#xff0c;交…

服务器日常怎么维护 有哪些

服务器日常维护主要包含两位部分&#xff1a;硬件维护和软件维护。硬件维护 硬件维护就是指对服务器的硬件进行检测&#xff0c;更换&#xff0c;升级&#xff0c;最常见的是防火墙更新&#xff0c;时刻能够应对市场上的变化。 也包含服务器环境的一些维护&#xff0c;定期检查…

SV-7042VP 15W sip网络有源音箱,可外接15W无源副音箱

SV-7042VP 15W sip网络有源音箱,可外接15W无源副音箱 一、描述 SV-7042VP是深圳锐科达电子有限公司的一款壁挂式SIP网络有源音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到功率15W。同时它可以外接一个15W的…

【GO语言卵细胞级别教程】01.GO基础知识

01.GO基础知识 目录 01.GO基础知识1.GO语言的发展历程2.发展历程3.Windowns安装4.VSCode配置5.基础语法5.1 第一段代码5.2 GO执行的流程5.3 语法规则5.4 代码风格5.5 学习网址 1.GO语言的发展历程 Go语言是谷歌公司于2007年开始开发的一种编程语言&#xff0c;由Robert Griese…

Java版直播商城免 费 搭 建:平台规划与常见营销模式,电商源码、小程序、三级分销及详解

【saas云平台】打造全行业全渠道全场景的saas产品&#xff0c;为经营场景提供一体化解决方案&#xff1b;门店经营区域化、网店经营一体化&#xff0c;本地化、全方位、一站式服务&#xff0c;为多门店提供统一运营解决方案&#xff1b;提供丰富多样的营销玩法覆盖所有经营场景…

游戏引擎?

游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需的各种工具&#xff0c;其目的在于让游戏设计者能容易和快速地做出游戏程式而不用由零开始。大部分都支持多种操作平台&#xff0c;如Linux、…

使用AOP实现自定义日志

在实现自定义日志之前&#xff0c;我们需要了解AOP。 1.AOP AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面编程&#xff09;是一种编程范式&#xff0c;旨在通过将横切关注点&#xff08;cross-cutting concerns&#xff09;从主要业务逻辑中分离出来&…

macOS跨进程通信: XPC 创建实例

一&#xff1a;简介 XPC 是 macOS 里苹果官方比较推荐和安全的的进程间通信机制。 集成流程简单&#xff0c;但是比较绕。 主要需要集成 XPC Server 这个模块&#xff0c;这个模块最终会被 apple 的根进程 launchd 管理和以独立进程的方法唤起和关闭&#xff0c; 我们主app 进…

【运维】界面操作与直接操作

对于一个大型的复杂的系统&#xff0c;各个模块之间紧密关联&#xff0c;界面上的一个操作&#xff0c;可能涉及到很多底层逻辑的连携反应。 在一个共享文件系统中&#xff0c;一个简单的小操作&#xff0c;可能就涉及到数据库多张表的改动&#xff0c;而且往往改动的表并不是…

Flume基础知识(四):Flume实战之实时监控单个追加文件

1&#xff09;案例需求&#xff1a; 实时监控 Hive 日志&#xff0c;并上传到 HDFS 中 2&#xff09;需求分析&#xff1a; 3&#xff09;实现步骤&#xff1a; &#xff08;1&#xff09;Flume 要想将数据输出到 HDFS&#xff0c;依赖 Hadoop 相关 jar 包 检查/etc/profile.d…

【MySQL】MySQL运维SQL(持续更新。。。)

MySQL运维SQL 信息统计 查询数据库有多少张表 SELECT COUNT(*) AS table_count FROM information_schema.TABLES WHERE table_schema 数据库名;查询表中有多少个字段 SELECTCOUNT(*) AS field_count FROMinformation_schema.COLUMNS WHEREtable_schema 数据库名 AND tab…

Spark内核解析-Spark shuffle6(六)

1、Spark Shuffle过程 1.1MapReduce的Shuffle过程介绍 Shuffle的本义是洗牌、混洗&#xff0c;把一组有一定规则的数据尽量转换成一组无规则的数据&#xff0c;越随机越好。MapReduce中的Shuffle更像是洗牌的逆过程&#xff0c;把一组无规则的数据尽量转换成一组具有一定规则…

RFID数据中心智能资产管理系统

数据中心机房承担着保障企业关键数据处理的重要责任&#xff0c;机房的日常管理直接关系到整体机房的日常维护和运行安全&#xff0c;数据资产管理中心在监管机房各部分设备的运行情况、维护数据中心的资产方面发挥着重要的作用。 成功的数据中心机房管理不仅需要选择高可靠性…

游戏分组(100用例)C卷 (JavaPythonC语言C++Node.js)

部门准备举办一场王者荣耀表演赛,有10名游戏爱好者参与,分为两队,每队5人。 每位参与者都有一个评分,代表着他的游戏水平。为了表演赛尽可能精彩,我们需要把10名参赛者分为实力尽量相近的两队。一队的实力可以表示为这一队5名队员的评分总和。 现在给你10名参与者的游戏水…

NFT 项目入驻 NFTScan Site 流程说明

NFTScan Site 是由数据基础设施 NFTScan 推出的功能强大的 NFT 项目管理平台。NFTScan Site 主要为 NFT Collection、NFT Marketplace、NFTFi 以及其他 NFT 生态项目提供专业的项目管理后台服务和链上数据分析追踪服务。 NFTScan Site 功能&#xff1a; 1&#xff09;项目信息编…

鸿蒙开发之Touch事件拦截stopPropagation()

在读Touch事件官方文档的时候&#xff0c;遇到了一个属性 其他属性都好理解&#xff0c;这个阻塞事件冒泡什么意思呢&#xff1f;官网也没有解释 后来查资料知道这个方法是阻止onTouch冒泡传递到父组件。 show code Entry Component struct OfficialTouchPage {State messa…

【leetcode100-30】【链表】两两交换链表节点

【题干】 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 【思路】 先说递归的&#xff0c;退出条件很明显&#xff0c;当剩…