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

news2025/5/26 5:15:28

● 控制反转,反转的是什么?
○ 将对象的创建权利交出去,交给第三方容器负责。
○ 将对象和对象之间关系的维护权交出去,交给第三方容器负责。
● 控制反转这种思想如何实现呢?
○ 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,剩下单词采用驼峰命名法,即mySySQLUserDao
    public 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 {
    @Test
    public 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 {
    @Test
    public void testConstructorDI(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring2_constructor.xml");
        CustomerService custormerService = applicationContext.getBean("customerServiceBean", CustomerService.class);
        custormerService.saveUsers();
    }
}

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

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

相关文章

通过IP地址如何进行网络安全防护

IP地址在网络安全防护中起着至关重要的作用&#xff0c;可以用于监控、过滤和控制网络流量&#xff0c;识别潜在威胁并加强网络安全。以下是通过IP地址进行网络安全防护的一些建议&#xff1a; 1. 建立IP地址白名单和黑名单&#xff1a; 白名单&#xff1a;确保只有授权的IP地…

UMLChina书籍大全(2024)软件方法人月神话人件企业应用架构模式UML参考手册彩色UML建模领域驱动设计对象设计……

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 以下列出有UMLChina标记的书。 首先是写了十几年还没有写完的软件方法 其他的是译作&#xff1a; 人月神话 2002年&#xff0c;UMLChina和清华大学出版社合作&#xff0c;翻译了《人…

老生常谈:Web 与低代码开发

Web技术和低代码平台是当前技术领域中的两个热门话题。它们在应用开发领域中扮演着重要的角色&#xff0c;不断被提及和讨论。本文将讨论为什么“Web与低代码”这个话题成为了“老生常谈”&#xff0c;探讨其背后的原因以及这两个概念的关系。 在当今技术飞速发展的时代&#x…

imgaug库指南(二):从入门到精通的【图像增强】之旅

文章目录 引言前期回顾代码示例小结结尾 引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应…

静态S5在项目管理中的应用与案例分享

静态S5作为一种强大的数据分析工具&#xff0c;不仅在数据处理和可视化方面表现出色&#xff0c;还在项目管理中发挥着重要作用。本篇将通过实际案例分享&#xff0c;探讨静态S5在项目管理中的应用与优势。 一、静态S5在项目管理中的应用 项目进度管理&#xff1a;静态S5通过…

每日一题——LeetCode1046.最后一块石头的重量

方法一 暴力排序 保证数组从小到大排序&#xff0c;所以最后两个就是最大的石头&#xff0c;每次取最后两个元素进行比较&#xff0c;一样重就直接下一次循环&#xff0c;不一样重就把两个石头重量差push进数组&#xff0c;把数组再次排序 循序嵌套sort排序时间复杂度较高&am…

基于SSM的汽车出租管理系统

目录 前言 开发环境以及工具 项目功能介绍 管理系统 详细设计 登录页面 客户信息管理 汽车信息管理 系统日志记录 汽车租赁功能 出租单入库检查功能 源码获取 前言 本项目是一个基于IDEA和Java语言开发基于SSM的汽车出租管理系统。应用包含管理系统&#xff1b; 汽…

LeetCode(33) 搜索旋转排序数组

整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], ..., nums[n-1], nums[0], nums[1], ..…

AD自动求导算法

Jacobian matrix 雅可比矩阵 在后面的前向反向积累会用到。AD需要用到中间变量的导数&#xff0c;所以Jacobian matrix就是来计算这些的。 Hessian矩阵 在牛顿法的优化中有应用。 牛顿法 Newton-type methods 自动求导 Automatic Differentiation, AD 数值微分 import n…

构建企业级AI中台,实现业务场景价值闭环

从数据资产到模型资产&#xff0c;大模型的发展&#xff0c;正在加速企业构建AI中台&#xff0c;旨在让更多 AI 的能力能够被构建出来、能够被管理起来、能够面向业务开放起来&#xff0c;打通从数据到模型到最后决策的全链路。 本文将从为什么建AI中台、如何建AI中台、企业AI…

盲盒、一番赏小程序搭建,打开线上盲盒市场

近几年&#xff0c;我国潮玩市场发展非常迅速&#xff0c;在互联网的影响下&#xff0c;盲盒更是迅速走红网络&#xff0c;深受年轻人的喜欢&#xff0c;各大社交平台上关于盲盒的讨论度也是层出不穷。 一番赏与盲盒的机制都是差不多的&#xff0c;盲盒是在包装一样的盒子中放…

ubuntu系统如何安装man命令的中文文档

ubuntu系统如何安装man命令的中文文档 背景 在Linux系统上需要使用一些命令的时候&#xff0c;往往会通过man命令去查询命令的使用方法和参数的说明&#xff0c;但是这些文档说明都是英文的&#xff0c;怎么样才能变成中文的文档&#xff0c;看上去更加清晰呢&#xff1f; 解…

到底谁还在用企业公示系统,聪明的人已经...

随着互联网和数字经济的发展&#xff0c;企业背调变得越来越重要了。毕竟现在企业数量不断增加&#xff0c;据调查数据显示&#xff1a;截止到23年8月11日全国市场总量已经达到3.4亿户&#xff0c;今年新增2049万户。 其中&#xff0c;企业总量9922万户&#xff0c;今年新增621…

线性代数-第五课,第六课,第七课,第八课

第五课 判断某向量是否可由某向量组线性表示 把向量组组成一个行列式&#xff0c;计算行列式的秩 把所有向量放在一起构成一个行列式&#xff0c;计算行列式的秩 如果两个行列式的秩相等&#xff0c;表示可以线性表示&#xff0c;写答案的格式如下 线性表示&#xff1a;bk…

深入浅出XTTS:Oracle数据库迁移升级利器

演讲大纲&#xff1a; 1. 什么是XTTS 2. 适用场景 3. XTTS的基本操作步骤 4. XTTS案例分享 今天主要跟大家分享一下XTTS,在网上曾看过相关讨论,但发现按网上讲的那些去实际操作的话,还是会遇到一些坑,并不能实际落下来,所以今天想跟大家分享一些实战干货. 一、什么是XTTS …

Linux第5步_测试虚拟机网络连接

安装好VMwareTools后&#xff0c;就可以测试虚拟机网络连接了&#xff0c;目的是实现虚拟机上网。 1、打开“控制面板”&#xff0c;得到下图&#xff1a; 2、双击“网络和 Internet” &#xff0c;得到下图&#xff1a; 3、双击“网络和共享中心” 4、点击“更改适配器设置”…

海康威视摄像头+服务器+录像机配置校园围墙安全侦测区域入侵侦测+越界侦测.docx

一、适用场景 1、校园内&#xff0c;防止课外时间翻越围墙到校外、从校外翻越围墙到校内&#xff1b; 2、通过服务器摄像头的侦测功能及时抓图保存&#xff0c;为不安全因素提供数字化依据&#xff1b; 3、网络录像机保存监控视频&#xff0c;服务器保存抓拍到的入侵与越界&am…

大数据时代的WEB运维高级架构师,Web系统运维工程师的实战成长之路

一、教程描述 本套WEB架构师教程&#xff0c;大小30.61G&#xff0c;共有183个文件。 二、教程目录 01-Web架构之单机时代&#xff08;共7课时&#xff09; 02-Web架构之集群时代&#xff08;共9课时&#xff09; 03-Web架构之DNS&#xff08;共6课时&#xff09; 04-Web…

2397. 被列覆盖的最多行数

给你一个下标从 0 开始、大小为 m x n 的二进制矩阵 matrix &#xff1b;另给你一个整数 numSelect&#xff0c;表示你必须从 matrix 中选择的 不同 列的数量。 如果一行中所有的 1 都被你选中的列所覆盖&#xff0c;则认为这一行被 覆盖 了。 形式上&#xff0c;假设 s {c1…

肿瘤til细胞类型

TISCH (comp-genomics.org)