【Spring】分别基于XML、注解和配置类实现Spring的IOC(控制反转)

目录

1、理解loC是什么

2、基于XML实现Spring的IOC(这种方式已经不怎么使用了)

3、基于注解实现Spring的IOC

4、基于javaConfig实现Spring的IOC

5、总结

1、理解loC是什么

lOC:lnversion of Control 控制反转,简称就是 IOC

控制反转:控制(对象创建权利)被反转

        控制反转通过依赖注入(DI)方式实现对象之间的松耦合关系。程序运行时,依赖对象由辅助程序动态生成并注入到被依赖对象中,动态绑定两者的使用关系。Spring IoC 容器就是这样的辅助程序,它负责对象的生成和依赖的注入,然后再交由我们使用。

        依赖注入(DI)Dependency Injection,它是 spring 框架核心 ioc 的具体实现。其作用是去除Java类之间的依赖关系,实现松耦合,以便于开发测试。

假设我现在有两个java类,UserService 和 UserDao,然后 UserService 中有依赖 UserDao,这时候创建 UserService 有如下两种情况:

用IOC之前:由程序员控制创建对象

        自己创建对象:UserService(new UserDao())---->UserDao;这种方式具有强耦合,再小的代码变更都会引起BUG的可能性

        比如在UserService类中要用到UserDao类,就需要在UserService类中创建UserDao类的对象,这就会造成类之间的强耦合。写代码的耦合度越高,对后期的维护就越不利,比如说以后要把UserDao类给换掉的话,就必须来到UserService类中把UserDao类的对象代码给换掉,如果有几十处,就要改几十处,但是再小的代码变更都会引起BUG的可能性

用IOC之后:创建对象依赖Spring注入(DI)

        Spring(new UserService(); new UserDao();) 由Spring来创建UserService类和UserDao类的对象,如果UserService中要用到UserDao就让Spring把UserDao注入进来

        如果需要用到Spring管理的对象,需要依赖Spring注入(DI)

        loC/DI优点:解耦,管理好对象的创建和依赖,总的来说就是统一管理对象。某一个对象只会创建一次,可以节省内存的开支,这属于设计模式当中的一种,设计模式有23种,这种属于单例设计模式,Sprig的管理对象就用到了这个单例设计模式,但是我们自己也可以把他改成每一次用到都给他创建一次

 没有引入Spring降低耦合度的方式:

        这种方式就是,创建一个接口,通过把将来可能要换的类去实现这个接口,使用时都是用这个接口的实现类,当需要把这个实现类换掉的时候,就只需要再创建这个接口的实现类,然后把之前的那个实现类换成这个新创建的实现类就可以了

示例:

//定义接口
public interface IUserDao {
    //执行查询用户
    void getUser();
}

//实现IUserDao接口的类,这个类在UserService中需要用到
public class UserDao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring");
    }
}

//UserService中需要用到UserDao,但是要降低和UserDao之间的耦合度
public class UserService {
    //用IUserDao来接收UserDao的实现类
    //这样当以后要把UserDao换成其他实现了IUserDao的类
    //就只需要把实现类(也就是现在UserDao的位置)改成要换的那个IUserDao实现类就可以了
    IUserDao userDao = new UserDao();
    //比如要换成User2Dao,只需要改成:IUserDao userDao = new User2Dao();就可以了
    public void getUser() {
        userDao.getUser();
    }
}

这种方式确实能够降低耦合度,但还是需要修改代码,而通过Spring的loC/Dl就可以实现不需要修改代码来降低耦合度

bean:在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。bean 是由Spring IoC 容器实例化、组装和管理的对象。 

2、基于XML实现Spring的IOC(这种方式已经不怎么使用了)

        通过在 xml 文件中用 <bean class=""> 这个标签的方式来进行显式的声明要配置成bean的类,生成 applicationContext.xml 文件步骤,但是要在pom.xml文件中引入spring-context依赖才会出现生成 applicationContext.xml 文件这一选项

bean 标签:在 Spring 的 XML 配置文件中配置一个 bean 标签,该标签最终会被加载为一个 BeanDefition 对象(描述对象信息),这个标签里面就用来描述要配置成bean的那个类的信息,这个标签里面像 ref、name 这些属性如果感兴趣的话可以去查阅一下,因为这种方式不怎么用了,所以这里就演示一下大概的流程

//pom.xml文件中需要引入的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.2</version>
</dependency>


//applicationContext.xml 文件配置
//在我的项目中,我把applicationContext.xml文件命名为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">

    <!--让Spring帮我们去new对象,对象之间的依赖也让spring帮我们进行组织-->
    <bean class="com.lt.service.UserService">
        <!--进行注入-->
        <property name="userDao" ref="userDao"></property>
    </bean>

    <bean class="com.lt.dao.UserDao" name="userDao"></bean>
    <bean class="com.lt.dao.User2Dao" name="user2Dao"></bean>
</beans>


//创建接口IUserDao
public interface IUserDao {
    //执行查询用户
    void getUser();
}


//接口IUserDao的实现类UserDao
public class UserDao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring");
    }
}


//接口IUserDao的实现类User2Dao
public class User2Dao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring 222");
    }
}


//创建接口IUserService
public interface IUserService {
    void getUser();
}


//接口IUserService的实现类UserService
//因为这种方式是基于get和set属性来进行注入的,所以要把UserService类的get和set方法声明一下
public class UserService implements IUserService{
    //耦合度过高 依赖spring注入(DI)
    IUserDao userDao;

    public IUserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
        userDao.getUser();
    }
}

//测试类
public class Test01 {
    @Test
    public void test(){
        //UserService userService = new UserService();
        //如果是自己new一个UserService,Spring是不会为这个自己new的UserService注入userDao的
        //要依赖spring注入,就需要从spring容器中获取UserService
        ClassPathXmlApplicationContext ico = new ClassPathXmlApplicationContext("spring.xml");
        IUserService service = ico.getBean(IUserService.class);
        service.getUser();
    }
}

注入UserDao时的运行结果 

注入User2Dao时的运行结果

 

3、基于注解实现Spring的IOC

通过 @component注解也可以将一个类声明为 Bean通过这种方式就不需要再在applicationContext.xml文件来进行复杂的添加每一个需要被配置成bean的类了

//applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!--告诉spring注解所在的包在哪,在com.lt包下面的包-->
<context:component-scan base-package="com.lt"></context:component-scan>

</beans>



//IUserDao是一个接口
public interface IUserDao {
    //执行查询用户
    void getUser();
}



@Component  //标识当前类交给spring去new(实例化),交给spring进行管理,spring组件-bean
public class UserDao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring");
    }
}



//@Component  //标识当前类交给spring去new(实例化),交给spring进行管理,spring组件-bean
public class User2Dao implements IUserDao{
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring 222");
    }
}


public interface IUserService {
    void getUser();
}


@Component
public class UserService implements IUserService{
    @Autowired  //让spring自动注入进来
    IUserDao userDao;

    @Override
    public void getUser() {
        userDao.getUser();
    }
}


public class Test01 {
    @Test
    public void test(){
        //UserService userService = new UserService();
        //如果是自己new一个UserService,Spring是不会为这个自己new的UserService注入userDao的
        //要依赖spring注入,就需要从spring容器中获取UserService
        ClassPathXmlApplicationContext ico = new ClassPathXmlApplicationContext("spring.xml");
        IUserService service = ico.getBean(IUserService.class);
        service.getUser();
    }
}

想要注入哪一个类就在那一个类上添加@Component注解

运行结果

 运行结果

4、基于javaConfig实现Spring的IOC

通过javaConfig(配置类)这种方式就不需要再在applicationContext.xml文件来配置要扫描的包是哪一个了,我们可以新建一个java类(javaConfig类)来代替这个xml文件,创建这个JavaConfig类,这里我把命名为SpringCopnfig,放在config文件下

ClassPathXmlApplicationContext 是基于xml配置的容器,这种方式不用xml文件了,所以用来获取对象的Spring容器也需要更改,这里需要用 AnnotationConfigApplicationContext 这个容器

然后就运行test02这个方法

相关代码:除了javaconfig(配置类)和测试方法的代码,其他代码没改动,和上面基于注解实现Spring的IOC中的代码一样

/*这个配置类就用来代替xml*/
@Configuration // = xml的配置文件
@ComponentScan("com.lt") //这个注解告诉spring要扫描的包在哪里,等于在xml文件中配置的 <context:component-scan 标签
public class SpringConfig {

}


public class Test01 {
    
    @Test  //测试基于 XML 实现Spring的IOC的方法
    public void test(){
        //如果是自己new一个UserService,Spring是不会为这个自己new的UserService注入userDao的
        //要依赖spring注入,就需要从spring容器中获取UserService
        //(我这里把获得的容器命名为 ioc)
        ClassPathXmlApplicationContext ico = new ClassPathXmlApplicationContext("spring.xml");
        IUserService service = ico.getBean(IUserService.class);
        service.getUser();
    }

    @Test  //测试基于 javaconfig 实现Spring的IOC的方法
    public void test02(){
        //如果是自己new一个UserService,Spring是不会为这个自己new的UserService注入userDao的
        //要依赖spring注入,就需要从spring容器中获取UserService
        //从spring容器中获取UserService(我这里把获得的容器命名为 ioc)
        AnnotationConfigApplicationContext ico = new AnnotationConfigApplicationContext(SpringConfig.class);
        IUserService service = ico.getBean(IUserService.class);
        service.getUser();
    }
}

5、总结

1.、spring1版本 纯xml文件的方式:这种方式中,如果要把某个类交给Spring帮我们管理,帮我们去 new 这个对象,那就需要把这个类在 xml 文件中配置成相应的 bean,如果要配置的 bean 非常的多的话,那这个 xml 文件的信息就会非常的多,也不利于我们后期的一个维护,开发的效率也非常的低(因为单单去编写这个 xml 文件都要花费许多时间)

 2、spring2版本 xml文件 + @(注解)的方式:在这种方式中,我们只需要在 xml 中配置一个扫描包,然后告诉他扫描的包路径,然后他就会通过这个包路径去扫描这个包下面所有的类,一旦发现类里面有个 @component 的注解,那他就会把当前这个类交给 spring 去管理,也就是把当前这个类配置成一个 bean (就是帮我们去 new 这个类的对象)。这中方式下就不需要像 纯xml 的方式那样去编写大量配置 bean 的信息了

3、spring3版本 javaconfig(配置类) + @(注解)的方式:这种方式中,只需要一个 javaconfig(配置类)就可以代替掉之前的 xml 配置文件

【java多线程】通过等待唤醒机制、局部变量、原子变量实现线程同步-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137122461?spm=1001.2014.3001.5501

【java多线程】线程同步问题:用同步代码块、同步方法和重入锁实现线程同步-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137022053?spm=1001.2014.3001.5501【Java多线程】多线程的三种实现方式和多线程常用方法-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/136961604?spm=1001.2014.3001.5501

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

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

相关文章

如何使用极狐GitLab Maven 仓库?

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何使用极狐GitLa…

Yarn与Zookeeper的介绍

Yarn--三大调度策略 FIFO(先进先出): 目前几乎已经没有人使用了. 类似于: 单行道. 好处: 每个计算任务能独享集群100%的资源. 弊端: 不能并行执行, 如果大任务过多, 会导致小任务执行时间过长. Capacity(容量调度): 我们用…

入门教程:Windows搭建C语言和EasyX开发环境

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; 如果对你…

【论文阅读】TimesNet: Temporal 2D-Variation Modeling for General Time Series Analysis

TimesNet: Temporal 2D-Variation Modeling for General Time Series Analysis 引用&#xff1a; Wu H, Hu T, Liu Y, et al. Timesnet: Temporal 2d-variation modeling for general time series analysis[C]//The eleventh international conference on learning representa…

学习 MongoDB:打开强大的数据库技术大门

一、基本概念 MongoDB 是一个基于分布式文件存储的文档数据库&#xff0c;由 C 语言编写。它旨在为 Web 应用提供可扩展的高性能数据存储解决方案。 相信MySQL我们非常的熟悉&#xff0c;那么MySQL的表结构与MongoDB的文档结构进行类比的话可能更好理解MongoDB。 MySQL的数据…

联通iccid 19转20 使用luhn 算法的计算公式

联通iccid 19转20 使用luhn 算法的计算公式 第一次对接iccid 才知道 使用的是luhn 算法 19转20位 文章来源于 文章来源 当时也是一脸懵逼 的状态&#xff0c;然后各种chatgpt 寻找&#xff0c;怎么找都发现不对&#xff0c;最后看到这片java的文章实验是正确的&#xff0c;因…

ubuntu生成core文件的设置方法

core文件可以很方便的帮助我们查找程序挂的问题&#xff0c;因此在程序挂后生成core文件的很有必要的。 1、查看ulimit参数 ulimit -a 如果core file size是0 需要设置其最大容量。按下面步骤操作 2、设置core文件大小&#xff0c;两种方法 临时生效&#xff0c;重启设备失…

WPF学习笔记-FlowDocument流文档基础知识和基本操作

文章目录 概述一、块元素和内联元素1.1 块元素&#xff08;Block类&#xff09;1.2 内联元素&#xff08;Inline类&#xff09;二、Paragraph元素2.1 基本属性设置2.2 将内联元素Inline添加到Inlines中2.3 设置中西文字体不一样 三、Table元素3.1 添加新的Table3.2 添加列3.3 添…

采用C#.net6.0+Vue,Ant-Design技术开发的一套大型医院手术麻醉信息系统源码,系统成熟,运行稳定

手术麻醉信息系统源码&#xff0c;C#手麻系统源码&#xff0c;自主版权应用案例&#xff08;适合上项目&#xff09; 手术麻醉信息系统可以实现手术室监护仪、麻醉机、呼吸机、输液泵等设备输出数据的自动采集&#xff0c;采集的数据能据如实准确地反映患者生命体征参数的变化&…

前端、后端上传文件到OSS,简明记录

前端、后端上传文件到OSS&#xff0c;简明记录 上传文件到oss的方式&#xff1a; **后端上传&#xff1a;**文件先要从页面上传到后端存起来&#xff0c;再通过后端发送到oss&#xff0c;然后后端将存起来的文件删除&#xff08;当然可以不删&#xff09;。 **前端上传&…

Unix 网络编程, Socket 以及bind(), listen(), accept(), connect(), read()write()五大函数简介

Unix网络编程是针对类Unix操作系统&#xff08;包括Linux、BSD以及其他遵循POSIX标准的操作系统&#xff09;进行网络通信开发的技术领域。网络编程涉及创建和管理网络连接、交换数据以及处理不同层次网络协议栈上的各种网络事件。在Unix环境中&#xff0c;网络编程通常涉及到以…

华为ensp中ospf多区域管理 原理及配置命令(详解)

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; ————前言———— OSPF 多区域的主要作用是缩小链路状态数据库和路由表的规模&#xff0c;减少路由更新的频率&#xff0c;提高网络的可扩展性&#xff0c;实现路由过滤和路由汇总&#xff0…

交通标志识别项目 | 基于Tensorflow+SSD实现道路交通标志识别

项目应用场景 面向智能驾驶或自动驾驶场景道路道路交通标志的识别&#xff0c;在交通标志识别的基础上为下一步的智能决策提供前提 项目效果&#xff1a; 项目细节 > 具体参见项目 README.md (1) 安装依赖 Python3.5、TensorFlow v0.12.0、Pickle、OpenCV-Python、Matplotl…

如何利用CSS实现文字滚动效果

1. 使用CSS3的animation属性 CSS3的animation属性可以让元素在一段时间内不停地播放某个动画效果。我们可以利用这个特性来实现文字滚动效果。 我们需要定义一个包含所有需要滚动的文本的容器元素。比如&#xff1a; <div class"scroll-container"><p>…

手机一键换ip地址,解锁网络自由

在数字化时代&#xff0c;手机已经成为我们生活中不可或缺的一部分。随着移动互联网的快速发展&#xff0c;手机用户对于网络安全和隐私保护的需求也日益增强。其中&#xff0c;IP地址作为手机在网络中的标识&#xff0c;扮演着重要的角色。有时&#xff0c;出于隐私保护或网络…

仿真黑科技EasyGo DeskSim 2022

DeskSim2022的FPGA支持多种solver的混合应用&#xff0c;对于每一种solver可以采用不同的仿真步长&#xff0c;以下图模型为例&#xff0c;模型运行在FPGA上&#xff0c;FPGA解算方式采用的是Power Electronic & FPGA Coder解算&#xff0c;其中电力电子电路部分采用了两种…

【opencv】教程代码 —features2D(6)透视矫正:读取两个棋盘格图片并进行图像对齐...

perspective_correction.cpp 透视校正 hconcat(img2, img1_warp, img_draw_warp); hconcat(img1, img2, img_draw_matches); #include <iostream> // 引入iostream库&#xff0c;用于进行标准输入和输出操作 #include <opencv2/core.hpp> // 引入opencv的core库&am…

Redis 主从复制集群搭建及其原理

目录 前言 配置文件 启动服务 配置主从关系 两种配置方式 slaveof 配置文件 补充 缺点 认证 复制原理 全量同步 增量同步 前言 单机的 redis 的性能虽然已经很强大了&#xff0c;但是随着业务的扩展&#xff0c;总有一天会遇到性能瓶颈&#xff0c;针对高并发带来…

cJSON(API的详细使用教程)

我们今天来学习一般嵌入式的必备库&#xff0c;JSON库 1&#xff0c;json和cJSON 那什么是JSON什么是cJSON&#xff0c;他们之间有什么样的关联呢&#xff0c;让我们一起来探究一下吧。 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&…

注意力机制篇 | YOLOv8改进之添加DAT注意力机制

前言:Hello大家好,我是小哥谈。DAT(Vision Transformer with Deformable Attention)是一种引入了可变形注意力机制的视觉Transformer。在训练算法模型的时候,通过引入可变形注意力机制,改进了视觉Transformer的效率和性能,使其在处理复杂的视觉任务时更加高效和准确。�…