首页 > 其他分享 >Spring IoC(控制反转)、DI(依赖注入)

Spring IoC(控制反转)、DI(依赖注入)

时间:2023-12-28 11:32:17浏览次数:34  
标签:Mapper String Service DI Spring syrdbt IoC public 注入


1. IoC

IoC(Inversion of Control,控制反转) 面向对象的一种设计思想,很多语言的框架都使用了IoC这个设计思想,并非特属于
Spring,其实现为将实例对象交给第三方容器管理,创建实例对象的时候,注入这些实例对象所依赖的实例对象,而不是在内部创建。所谓的内部创建如下所示,连接数据库的DateSource,在默认构造函数直接初始化属性值:

/**
 * @author syrdbt
 * @date 2020-11-15
 */
public class DateSource {

   private String dataBaseUrl;

   private String userName;

   private String password;

    public DateSource() {
    }

    public DateSource() {
        String dateBaseUrl = new String("127.0.0.1:3306");
        String userName = new String("syrdbt");
        String password = new String("syrdbt");
    }
}

使用DateSource如下所示:

public class Main {
    public static void main(String[] args) {
        DataSource dataSource = new DataSource();
    }
}

使用 IoC 之后,你只需定义一个如下的DateSource类:

/**
 * @author syrdbt
 * @date 2020-11-15
 */
public class DateSource {

   private String dataBaseUrl;

   private String userName;

   private String password;

    public DateSource() {
    }

    public DateSource(String dataBaseUrl, String userName, String password) {
        this.dataBaseUrl = dataBaseUrl;
        this.userName = userName;
        this.password = password;
    }
   
}

获取DataSource实例的时候,使用一个管理这个实例的容器工厂去获取,上面实例化的127.0.0.1:3306、syrdbt等信息,在其他地方配置即可,例如XML文件中,容器会去读取XML文件这些配置:

public class Main {
    public static void main(String[] args) {
        // 读取第三方配置中的数据、并将DataSource放入容器之中
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取该DataSource实例
        DataSource dataSource = Factor.get("dataSource");
}

2. 依赖注入(DI)

依赖注入(Dependency Injection)是Spring框架实现控制反转的方式。

依赖注入有三种方式:构造函数注入、属性注入 和 接口注入。

2.1 构造函数注入

Service类如下所示。

/**
 * @author syrdbt
 * @date 2020-11-14
 */
public class Service {

   private Mapper mapper;

    public Service(Mapper mapper) {
        this.mapper = mapper;
    }
}

Service 使用构造函数注入 Mapper如下所示:

public static void main(String[] args) {
        // 注入Mapper实例
        Service service = new Service(new Mapper());
    }
2.2 属性注入

Service 类如下所示:

/**
 * @author syrdbt
 * @date 2020-11-14
 */
public class Service {

    private Mapper mapper;

    public void setMapper(Mapper mapper) {
        this.mapper = mapper;
    }
}

使用属性注入如下所示:

public static void main(String[] args) {
        Service service = new Service();
        // 注入Mapper实例
        service.setMapper(new Mapper());
    }
2.3 接口注入

Service 接口如下所示:

/**
 * @author syrdbt
 * @date 2020-11-14
 */
public interface Service {
    void init(Mapper mapper);
}

需要去实现这个接口:

/**
 * @author syrdbt
 * @date 2020-11-14
 */
public class ServiceImpl implements Service {
    
    private Mapper mapper;
    
    @Override
    public void init(Mapper mapper) {
        this.mapper = mapper;
    }
    
}

调用方法注入实例,通过接口注入,需要额外声明接口,增加了类的数量,但效果和属性注入是一样的。

public static void main(String[] args) {
        Service service = new ServiceImpl();
        // 注入Mapper实例
        service.init(new Mapper());
    }
2.4 不使用依赖注入的情况

不使用依赖注入就会导致代码耦合,如下所示。

/**
 * @author syrdbt
 * @date 2020-11-14
 */
public class Service {


    private Mapper mapper;

    public Service() {
        this.mapper = new Mapper();
    }

    public static void main(String[] args) {
        // 无需注入
        Service service = new Service();
    }
}

通过上述四个例子,你会发现依赖注入其实是一个很简单的概念。

3. Spring IoC 中的依赖注入

3.1 Spring IoC 中的依赖注入实例

Spring 支持属性注入和构造注入两种注入方式构建Bean实例。

People 类如下所示,People 就是一个调用者:

package com.study.syrdbt.entity;

/**
 * @author syrdbt
 * @date 2020-10-10
 */
public class People {

    private String name;

    private Integer age;

    public People() {
    }

    public People(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

将 name 和 age 注入到 People 中,可以在 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 id="syrdbt" class="com.study.syrdbt.entity.People">
        <property name="name" value="syrdbt"></property>
        <property name="age" value="23"></property>
    </bean>

    <!-- 构造器注入 -->
    <bean id="syrdbt1" class="com.study.syrdbt.entity.People">
        <constructor-arg index="0">
            <value>syrdbt</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>233</value>
        </constructor-arg>
    </bean>

</beans>

测试类:

package com.study.syrdbt;

import com.study.syrdbt.entity.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author syrdbt
 * @date 2020-10-10
 */
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        People syrdbt = (People) context.getBean("syrdbt");
        System.out.println(syrdbt.toString());
        People syrdbt1 = (People) context.getBean("syrdbt1");
        System.out.println(syrdbt1.toString());
    }
}

测试结果如下图所示:

Spring  IoC(控制反转)、DI(依赖注入)_xml

3.2 Spring 如何使用 xml 文件去注入

第一步:读入XML文件;
第二步:解析XML文件,生成Bean对象,并存放在一个容器中(其实就是一个Map接口,key为xml中的id,value为实例)
第三步:通过id去访问这些Bean对象。

Spring 的内部实现当然不是上面三步那么简单,上面只不过是大致流程。

如下创建一个 id 为 syrdbt 的 Bean 实例,你需要指明它是哪一个类,这里指明为 com.study.syrdbt.entity.People,然后就可以通过这个目录位置,通过反射创建实例,并且调用其 set 方法注入设置的两个值 name=‘syrdbt’, age=233 。

<bean id="syrdbt" class="com.study.syrdbt.entity.People">
        <property name="name" value="syrdbt"></property>
        <property name="age" value="23"></property>
    </bean>

做一个小小的测试,我们注释了无参构造函数,无法进行属性注入了,因为无法生成实例,再去调用 set 方法。

Spring  IoC(控制反转)、DI(依赖注入)_属性注入_02


在进行如下修改,我们对 setName 方法进行参数打印,并注释掉了 setAge 方法,如下图所示,我们成功调用了 setName 方法。

Spring  IoC(控制反转)、DI(依赖注入)_依赖注入_03


如下图所示:找不到 age 的 set 方法,无法进行属性注入。

Spring  IoC(控制反转)、DI(依赖注入)_xml_04

参考文献

  • 精通 Spring 4.x 企业应用开发实战 陈雄华老师、林开雄老师、文建国老师
  • Spring 实战第 4 版
  • Spring 中文官方文档


标签:Mapper,String,Service,DI,Spring,syrdbt,IoC,public,注入
From: https://blog.51cto.com/xuxiangyang/9012041

相关文章

  • Spring之RestTemplate使用小结
    Spring之RestTemplate使用小结1.基本接口捞出源码,看一下其给出的一些常用接口,基本上可以分为下面几种//get请求public<T>TgetForObject();public<T>ResponseEntity<T>getForEntity();//head请求publicHttpHeadersheadForHeaders();//post请求publicURI......
  • PredicateBuilder
    usingGate.ExpressionBuilder;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Linq.Expressions;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Tasks;namespaceFast.Framework{publicstaticclassP......
  • Docker 部署 Prometheus Webhook DingTalk
    介绍在此部分简要介绍PrometheusWebhookDingTalk的作用和使用Docker部署的优势。概述将要涵盖的常用参数以及如何配置Docker容器的关键概念。步骤1:获取PrometheusWebhookDingTalk代码解释如何获取PrometheusWebhookDingTalk的代码并进入存储库目录。gitcloneh......
  • 【AI编程工具】目前市面上常见的AI代码助手(AI Coding Assistant)
    目前市面上常见的AI代码助手(AICodingAssistant)有:GithubCopilot:提供更高效的代码编写、学习新的语言和框架以及更快的调试通义灵码_智能编码助手_AI编程_人工智能-阿里云AmazonCodeWhisper:实时代码建议CodeGeeX:国产免费编程AI助手iFlyCode:科大讯飞发布的编程新时代的智能助手Com......
  • 【Spring】SpringMVC项目升级成SpringBoot实践
    将SpringMVC项目升级为SpringBoot项目需要一系列详细的步骤。以下是一个更详细的步骤指南:项目初始化:创建一个新的SpringBoot项目。您可以使用SpringInitializr或SpringBoot的Maven插件来快速生成项目结构。依赖管理:在新项目中,添加所需的依赖。根据您的项目需求,添加SpringBoot......
  • uniapp实战 -- 个人信息维护(含选择图片 uni.chooseMedia,上传文件 uni.uploadFile,获取
    效果预览相关代码页面–我的src\pages\my\my.vue<!--个人资料--><viewclass="profile":style="{paddingTop:safeAreaInsets!.top+'px'}"><!--情况1:已登录--><viewclass="overview"v-if="mem......
  • 【PXIE301-208】基于PXIE总线架构的Serial RapidIO总线通讯协议仿真卡
    板卡概述PXIE301-208是一款基于3UPXIE总线架构的SerialRapidIO总线通讯协议仿真卡。该板卡采用Xilinx的高性能Kintex系列FPGA作为主处理器,实现各个接口之间的数据互联、处理以及实时信号处理。板卡支持4路SFP+光纤接口,支持一个PCIex8主机接口,板载1组独立的64位DDR3SDRAM大容......
  • Redis过期删除策略
    定时删除;惰性删除;定期删除;定时删除策略是怎么样的?定时删除策略的做法是,在设置key的过期时间时,同时创建一个定时事件,当时间到达时,由事件处理器自动执行key的删除操作。定时删除策略的优点:可以保证过期key会被尽快删除,也就是内存可以被尽快地释放。因此,定时删除对内存......
  • #星计划# DevEco Studio Profiler工具分析应用启动性能
    LaunchProfiler概述DevEcoStudio内置Profiler分析调优工具,其中Launch主要用于分析应用或服务的启动耗时,分析启动周期各阶段的耗时情况、核心线程的运行情况等,协助开发者识别启动缓慢的原因。此外,Launch任务窗口还集成了Time、CPU、Frame场景分析任务的功能,方便开发者在分析启动......
  • 控制反转 (IoC)
    在传统的软件设计中,程序的控制流程是由程序本身决定的。这意味着程序定义了各种组件何时以及如何创建、使用和销毁。相比之下,IoC是一种设计原则,它规定将控制从程序转移到外部实体(IoC容器或框架)。在IoC驱动的设计中,组件及其生命周期由IoC容器管理,该容器负责创建、初始化这些......