01Spring的Ioc思想和依赖注入手段(DI)

2023-09-17 10:06:29

传统方式创建对象的缺陷

连接MySQL实现登录功能

控制层UserController

public class UserController {
    //多态,半面向接口编程
    private UserService userService = new UserServiceImpl();
    public void login(){
        String username = "admin";
        String password = "123456";
        boolean success = userService.login(username, password);
        if (success) {
            // 登录成功
        } else {
            // 登录失败
        }
    }
}

业务层的UserService接口及其实现类UserServiceImpl

public interface UserService {
    boolean login(String username, String password);
}

public class UserServiceImpl implements UserService {
	//多态,面向接口编程
    private UserDao userDao = new UserDaoImplForMySQL();
    public boolean login(String username, String password) {
        User user = userDao.selectByUsernameAndPassword(username, password);
        if (user != null) {
            return true;
        }
        return false;
    }
}

数据访问层的UserDao接口及其实现类UserDaoImplForMySQL

public interface UserDao {
    User selectByUsernameAndPassword(String username, String password);
}

public class UserDaoImplForMySQL implements UserDao {
    public User selectByUsernameAndPassword(String username, String password) {
        // 连接MySQL数据库,根据用户名和密码查询用户信息
        return null;
    }
}

功能扩展连接Oracle实现登录

若更换到Oracle数据库上则需要再提供一个UserDaoImplForOracle, 这样就引起了连锁反应,UserServiceImpl类代码需要修改违背了OCP开闭原则

public class UserDaoImplForOracle implements UserDao {
    public User selectByUsernameAndPassword(String username, String password) {
        // 连接Oracle数据库,根据用户名和密码查询用户信息
        return null;
    }
}

public class UserServiceImpl implements UserService {
    // 在进行功能扩展的时候修改了源代码, 违背了OCP开闭原则
    // private UserDao userDao = new UserDaoImplForMySQL();
    private UserDao userDao = new UserDaoImplForOracle();

    public boolean login(String username, String password) {
        User user = userDao.selectByUsernameAndPassword(username, password);
        if (user != null) {
            return true;
        }
        return false;
    }
}

软件七大开发原则(为解耦合服务)

OCP开闭原则

对外扩展开放修改关闭: 软件开发过程中若在进行功能扩展的时候添加额外的类是没问题的,但因为功能扩展而修改之前运行正常的程序这是不被允许的

  • 因为一旦修改之前运行正常的程序,就会导致项目整体要进行全方位的重新测试(这是相当麻烦的过程)

传统方式的MVC架构,上层是依赖下层的代码之间的耦合度太高, 这样会导致只要下面改动上面必然也需要改,所谓牵一发而动全身
在这里插入图片描述

依赖倒置原则DIP

依赖倒置原则(Dependence Inversion Principle): 就是倡导面向抽象编程,完全面向接口编程,不要面向具体编程

  • 上层不再依赖下层,即下面改动了上面的代码不会受到牵连 , 这样可以大大降低程序的耦合度,耦合度低了扩展力就强了,同时代码复用性也会增强

半面向接口编程: 对象的创建和属性的赋值都是手动, 使用到了具体的接口实现类

public class UserServiceImpl implements UserService {
    //private UserDao userDao = new UserDaoImplForMySQL();
    private UserDao userDao = new UserDaoImplForOracle();
    public boolean login(String username, String password) {
        User user = userDao.selectByUsernameAndPassword(username, password);
        if (user != null) {
            return true;
        }
        return false;
    }
}

完全面向接口编程:对象的创建是自动的, 属性也是自动赋值的, 但是在执行的时候需要解决空指针异常的问题

  • 第一个问题:谁来负责对象的创建【new UserDaoImplForOracle() 或者 new UserDaoImplForMySQL()】
  • 第二个问题:谁来负责把创建的对象赋到这个属性上【把上面创建的对象赋给userDao属性】
public class UserServiceImpl implements UserService {
    //private UserDao userDao = new UserDaoImplForMySQL();
    //private UserDao userDao = new UserDaoIm   plForOracle();
    private UserDao userDao;
    public boolean login(String username, String password) {
        User user = userDao.selectByUsernameAndPassword(username, password);
        if (user != null) {
            return true;
        }
        return false;
    }
} 

控制反转IoC思想

控制反转(Inversion of Control)是面向对象编程中的一种设计思想或一种新型的设计模式(由于理论和时间成熟相对较晚,没有被纳入GoF23种设计模式范围内)

  • 当程序既违背OCP又违背DIP时, 可以采用“控制反转”这种编程思想来解决问题 , 可以用来降低代码之间的耦合度
  • 控制是控制资源的获取方式是主动还是被动 , 反转是将对象的创建权交出去,将对象和对象之间关系的维护权交出去,由第三方容器来负责创建与维护

依赖注入手段(DI)

依赖注入是实现控制反转这种思想的一种常用实现手段 , 底层使用的是反射机制给属性赋值

  • 依赖(Dependency):对象和对象之间的关联关系, 如A类中有一个B类型的属性就说明A依赖了B
  • 注入(Injection):一种数据传递行为,如给A对象的B类型的属性赋值 ,让A类型的对象和B类型的对象产生了关系(靠注入的手段来维护A和B之间的关系)
  • Spring通过依赖注入的方式来完成Bean管理(实现Bean对象的创建以及Bean对象中属性的赋值或者叫做Bean对象之间关系的维护)

依赖注入常见的实现方式包括两种

  • set注入(执行set方法给属性赋值)
  • 构造方法注入(执行构造方法给属性赋值)
更多推荐

Linux系统100条命令:关于Ubuntu和 CentOS 7 相同功能的不同的终端操作命令

安装软件包:Ubuntu:apt-getinstallpackage_nameCentOS7:yuminstallpackage_name更新软件包列表:Ubuntu:apt-getupdateCentOS7:yumupdate卸载软件包:Ubuntu:apt-getremovepackage_nameCentOS7:

Vue学习笔记

本博客记录Vuev2.7.8的学习,参考文档目录Vue概述入门案例Vue指令v-bind和v-modelv-onv-if和v-showv-for综合案例生命周期Vue概述一个完整的html页面包括了视图和数据,数据是通过请求从后台获取的,那么意味着我们需要将后台获取到的数据呈现到页面上,很明显,这就需要我们使用DOM操

机器学习的基本代码

步骤1:导入必要的库```pythonimportpandasaspdfromsklearn.feature_extraction.textimportCountVectorizerfromsklearn.naive_bayesimportMultinomialNBfromsklearn.metricsimportac

易基因直播预告|细菌微生物基因表达调控表观研究易基因科技

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。DNA甲基化是在半个多世纪前在细菌中发现的。DNA碱基可以作为一个表观遗传调节因子——也就是说,它可以赋予相同的基因序列不同的和可逆的调控状态。在真核生物中,表观遗传调控可以发生在多个水平上:DNA甲基化、核小体定位、组蛋白变异和组蛋白修饰。相比之下,细菌缺

【云原生】kuberneter中Helm入门到实践

引言helm是k8s的包管理工具,使用helm,可以使用更为简化和系统化的方式对k8s应用进行部署、升级。helm是CNCF已毕业的项目,社区也是相当活跃的,在https://artifacthub.io/上,能找到很多现成的helmchart,稍作修改就能用到生产环境中,非常方便。本文会介绍helm的核心概念,并用一

Vim的基础操作

前言本文将向您介绍关于vim的基础操作基础操作在讲配置之前,我们可以新建一个文件.vimrc,并用vim打开在里面输入setnu先给界面加上行数,然后shift+;输入wq退出默认打开:命令模式本文将下来会主要讲这几种模式,当然vim还有其他一些特殊模式,但是比较少用在命令模式中:h:向左移动j:向下移动k:向上移动L

自学 Java 需要具备哪些基本条件或技能?

新手初学者在自己学习Java时,需要注意两个方面,一个是学习方面,一个是知识点方面!学习方面:1、做学习计划并保持自律在我们学习Java的过程中,尽量减少干扰,把自己的全部注意力集中在Java上。无论你注意力的持续时间是多久,都应该将全部精力放在Java上。2、通过编码来学习很多新手在学习Java时都会经历一个阶段,那

vue中通过JavaScript实现web端鼠标横向滑动&触控板滑动效果-demo

JavaScript实现web端鼠标横向滑动&触控板滑动效果支持鼠标拖动滑动&触控板滑动效果web端实现滑动,就是对鼠标按下、鼠标松开、鼠标移动事件进行监听效果图代码结构代码<template><divclass="swiper"><divclass="container"ref="container"><!--在这里

计算机视觉与深度学习-全连接神经网络-训练过程-批归一化- [北邮鲁鹏]

文章目录思想批归一化操作批归一化与梯度消失经过BN处理算法实现思想直接对神经元的输出进行批归一化批归一化:对输出值进行归一化,将归一化结果平移缩放作为输出。批归一化操作小批量梯度下降算法回顾:每次迭代时会读入一批数据,比如32个样本;经过当前神经元后会有32个输出值y1,…y32。批归一化操作:对这32个输出进行减均值

Java实现Modbus Tcp协议读写模拟工具数据

标题前言一、读写模拟工具中数据(1)定义Controller层(2)定义Service层实现二、调试(1)读数据(2)向寄存器写单个数据(3)向寄存器写多个数据前言参考文章:https://www.cnblogs.com/ioufev/p/10831289.html该文中谈及常见的几种读取设备数据实现,说到modbus

【CNN-FPGA开源项目解析】01--floatMult16模块

文章目录(基础)半精度浮点数的表示和乘运算16位半精度浮点数浮点数的乘运算floatMult16完整代码floatMult16代码逐步解析符号位sign判断指数exponent计算尾数fraction计算尾数fraction的标准化和舍位整合为最后的16位浮点数结果[sign,exponent,fraction]其他变

热文推荐