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,剩下单词采用驼峰命名法,即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();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI模型必选

国内AI人工智能站点 下面来分享一下国内的AI网站 最底下有直接的入口 1、国内使用chatGPT接口二次开发的网站&#xff0c;有很多我随便发一个 https://chat18.aichatos.xyz/#/chat/2、“通义千问”&#xff1a;阿里云推出的一个超大规模的语言模型 https://tongyi.aliyun.…

SpringBoot实现登录拦截器

SpringBoot实现登录拦截器 对于管理系统或其他需要用户登录的系统&#xff0c;登录验证都是必不可少的环节&#xff0c;在SpringBoot开发的项目中&#xff0c;通过实现拦截器来实现用户登录拦截并验证。 1、SpringBoot实现登录拦截的原理 SpringBoot通过实现HandlerIntercep…

three.js Raycaster(鼠标点击选中模型)

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div class"box-right"…

集合学习笔记(二)

文章目录 1.请介绍TreeMap的底层原理2. Map和Set有什么区别&#xff1f;3. List和Set有什么区别&#xff1f;4 .ArrayList和LinkedList有什么区别&#xff1f;5. 有哪些线程安全的List&#xff1f;6 .介绍一下ArrayList的数据结构&#xff1f;7. 谈谈CopyOnWriteArrayList的原理…

低代码:实现数据可视化的强大助手

随着数据在企业中的价值越来越受到重视&#xff0c;数据可视化成为了决策者和业务专家们必备的工具。然而&#xff0c;传统的数据可视化开发过程常常繁琐且耗时&#xff0c;限制了其在应用中的广泛应用。低代码平台的出现&#xff0c;为实现高效的数据可视化提供了新的解决方案…

使用Matplotlib绘制模拟上海城市气温变化图

模拟上海气温变化折线图 实现步骤 准备数据创建画布绘制图像显示图像 基本实现 示例代码&#xff1a; import matplotlib.pyplot as plt import random# 准备数据 x range(60) y_shanghai [random.uniform(15,18) for _ in x]# 创建画布 plt.figure(figure(20,8), dpi10…

位运算 (运算符)

文章目录 位运算位运算概述位运算概览& 按位与&#xff08;AND&#xff09;| 按位或&#xff08;bitwise OR&#xff09;^ 按位异或&#xff08;bitwise XOR&#xff09;~ 按位非&#xff08;bitwise NOT&#xff09;<< 左移&#xff08;bitwise shift left&#xff…

深入探究:使用大型AI模型的实战指南

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在今天的技术领域&#xff0c;大型AI模型已成为…

windows+django+nginx部署静态资源文件

平台&#xff1a;windows python&#xff1a;3.10.0 django&#xff1a;4.0.8 nginx&#xff1a;1.24.0 背景 开发阶段采用前后端分离模式&#xff0c;现在要将项目部署到工控机上&#xff0c;把前端项目编译出来的静态文件放到后端项目中进行一体化部署&#xff0c;且不修改…

告别复杂排版:Markdown语法指南

导语&#xff1a;Markdown作为一种轻量级的标记语言&#xff0c;以其简洁、易学的语法和强大的兼容性赢得了广泛的应用。本文将为您详细介绍Markdown的起源、基本语法及其在写作、博客、项目管理等场景的应用&#xff0c;带您领略这一简洁高效的文本编写工具的无穷魅力。 Mark…

「HarmonyOS」验证码多TextInput输入框焦点自动跳转问题

需求背景&#xff1a;需要做一个多输入框的验证码模块&#xff0c;输入验证码时输入后光标会自动跳转至下一个输入框&#xff0c;删除验证码时会自动删除上一个输入框内容&#xff0c;并且光标跳转至上一个输入框内。6位验证码全部输完后进行登录请求 具体样式如下图&#xff1…

前端angular 实现验证码 输入+展示(大框+加粗内容 )

参考用原生方在手机上此效果 如何实现一个4位验证码输入框效果 输入使用的任旧是html的input元素&#xff0c;只是让它看不到了只是把输入到input元素里的内容取到的内容放在改过样式的div里不需要dom操作&#xff0c;直接用双向绑定就拿到数据&#xff1b;使用动态样式 设置了…

全球大气二氧化碳浓度2°x2.5°栅格模拟数据集(1992-2020)

全球大气二氧化碳浓度2x2.5栅格模拟数据集&#xff08;1992-2020&#xff09; 全球大气二氧化碳浓度2x2.5栅格模拟数据集&#xff08;1992-2020&#xff09;是以2002-2012年全球对流层CO2浓度卫星遥感产品&#xff08;AIRS&#xff0c;AIRx3C2M 005&#xff09;为基础&#xff…

中国FinOps现状调查报告(2023)》亮点解读

今年以来&#xff0c;我们举办了多期FinOps的专题分享&#xff0c;邀请了美图、腾讯、B站、趣丸、知乎等厂商和行业专家&#xff0c;分享他们在FinOps领域的经验。我们也发现越来越多的人对FinOps产生了浓厚的兴趣&#xff0c;而且FinOps的成熟度也在逐渐提升。 降本增效&…

前端如何捕获网络问题导致的接口失败 net::ERR_NETWORK_IO_SUSPENDED

上传大文件时电脑休眠、页面静置导致接口报网络错误&#xff0c;上传失败 最近遇到了上传文件遇到网络波动、超时、网络中断情况下需要重传的需求刚开始排查只能在控制台看到报错net::ERR_NETWORK_IO_SUSPENDED&#xff0c;一头雾水。后加上catch捕获异常进行判断 fetch(/upl…

uniapp中uview组件库丰富的Slider 滑动选择器的使用方法

目录 #平台差异说明 #基本使用 #设置最大和最小值 #设置步进值 #禁用状态 #自定义按钮的内容和样式 #自定义滑动选择器整体的样式 #此页面源代码地址 #API #Props #Slider Events 该组件一般用于表单中&#xff0c;手动选择一个区间范围的场景。 说明 该组件在H5&…

如何制作可预约的上门维修服务小程序?

上门维修服务已经成为人们日常生活中不可或缺的一部分。为了满足这一需求&#xff0c;我们学习如何无经验自己制作上门维修服务小程序。 首先&#xff0c;打开乔拓云-门店系统的后台&#xff0c;可以看到有很多各行各业的模版。这些模版涵盖了各种行业&#xff0c;包括家电维修…

竞赛保研 基于机器视觉的行人口罩佩戴检测

简介 2020新冠爆发以来&#xff0c;疫情牵动着全国人民的心&#xff0c;一线医护工作者在最前线抗击疫情的同时&#xff0c;我们也可以看到很多科技行业和人工智能领域的从业者&#xff0c;也在贡献着他们的力量。近些天来&#xff0c;旷视、商汤、海康、百度都多家科技公司研…

Js的$如同 sed的 java的$0 指代matcher匹配到的内容的符号

Js的$&如同 sed的& java的$0 $& 可用于Js,Vscode,RJTextEd,editplus,notepad, 在 Vscode,RJTextEd,editplus,notepad,等的替换中, 启用正则, 就能使 $&生效, 比如 ($&)表示给匹配到的内容加上括号 $& 可用于Js的String的replace(和replaceAll( 的第二…

《软件方法(下)》8.2.4-8.2.5 类和属性的命名,审查类和属性(202401更新)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 8.2 建模步骤C-1 识别类和属性 8.2.4 类和属性的命名 8.2.4.2 关于DDD话语中的“通用语言” DDD&#xff08;领域驱动设计&#xff09;话语中有“通用语言&#xff08;Ubiquitous L…