对比 “直接调用” 与 “DLL 解耦” 的局限性
场景 直接调用 / 硬编码 DLL 解耦 依赖注入
实现替换成本 高(需修改所有调用点) 中(需修改实例创建) 低(仅修改注入配置)
测试隔离难度 难(依赖真实对象) 中(需手动创建 Mock) 易(直接注入 Mock 对象)
生命周期管理 无(手动管理) 无(依赖开发者约定) 强(容器自动管理)
复杂依赖关系处理 差(手动维护依赖图) 中(依赖物理分层) 强(容器自动解析依赖链)
框架集成友好度 低(需适配框架) 中(需约定接口) 高(框架原生支持)
是不是可以在配置文件里注入,注入后源代码如果替换依赖项,能直接在配置文件直接替换依赖名称?不用修改封装好的代码,也就是aop
@KyrieLee: 是的,依赖注入的配置文件可以实现无需修改代码即可替换依赖项,这是依赖注入(DI)的核心优势之一。这种机制通过将依赖关系从代码中解耦到外部配置中,使得依赖的替换仅需修改配置文件即可完成。
@KyrieLee: 这个只是注册服务的其中一种方式,其他方式需要参照使用的Ioc工具框架的支持哪种方式
主要是解决类的实例化问题,让实例化变得自动化。我是这样理解的。
是不是可以在配置文件里注入,注入后源代码如果替换依赖项 也需要换个名字,那跟直接改一下new的类名有啥区别,还是说能在配置项直接管理?不用修改封装好的代码,也就是aop
@KyrieLee:启动时加句代码获取配置项注入不就行了嘛!没必要纠结.
依赖注入要和控制反转结合起来看,控制反转就是调用者不用关心注入对象的实例化过程,也不用关心注入接口的具体是哪个对象被实例化,当注入对象/接口实例化过程的变化还是什么样的生命周期(单例、临时、其他等)调用方不需要关心,也就是注入方式没变化,后者是目的是核心思想,前者是方式是写法(如果通过构造函数注入、属性注入、特性注入等方式)
使用依赖注入管理了对象的如何实例化后, 就可以统一管理, 例如和切面编程结合,在实例化返回附着切面的代理对象, 或者比较耗能的资源可以通过懒加载甚至异步加载来实例化对象(不用依赖注入你需要每个对象都需要处理下,有了它你可以指定实例化策略,统一处理)。 如果了解spring 生态的话, 你仔细研究下会发现依赖注入就是Spring的基石,后面所有的组件都是围绕spring context(依赖注入实现的ioc容器) 扩展的
就是没太多技术含量的工程标准化(都能一眼看懂,好比ado.net至于mybatis,前者会出现各种写作方式,后者规范既定方式),对于写(实现)框架来说通常用不上。就像asp.net(当然j2ee也差不多)搞一堆service,让你用啥就标注一下就能使用一个道理。如果就语言和软件的程序设计来说,是开倒车的,因为设计需要灵活,通过灵活巧妙的设计规范和简化上层使用;对于规范来说,软件工程的意义是重大的,尤其是webForm时代之于j2ee,两者的可读可改性一个天上一个地下。
1、最少知道原则的最佳体现(迪米特法则)
例子:当我将nlog组件引入我项目时,我希望简单一句service.addNlog('配置信息')就可以直接使用微软的Ilogger接口来替换掉微软的底层logger实现,我在开发中只需要引入Ilogger类型就可以实现日志功能。反过来想,如果不使用依赖注入,是不是我得基于每个操作来实例化nlog
2、解耦
当我开心的一顿引入依赖然后撸码最后debug时候,报错了:检测到循环依赖,程序无法启动。
原因是A依赖B,B又依赖A。这是依赖注入会遇到的一个问题,但其实仔细回溯起来是我自身模块的设计问题,就会有这样的问题,当我们代码中出现这种情况时,往往是一个类的职责已经发生了偏离,我需要重新审视我为什么要设计这两个类,当时设计这两个类的初衷是不是有问题
以上是我用了这么久的依赖注入自己产生的心得,希望可以帮到你