`

spring和依赖注入的价值

    博客分类:
  • java
阅读更多
看到有帖子,置疑spring和依赖注入的价值,回复内容整理如下:

依赖注入对设计有利,而spring则促进了依赖注入的使用。

如果业务处理类,它所使用的倚赖,都是依靠在这个类内部实现或者查找,那么必然使得正常的业务逻辑和获取依赖的方法混在一起。

我取个最简单的场景,某个注册的工作类,它需要获取当前"容许的用户名的最大长度",这个依赖非常简单吧?基本每个注册类都有这个限制,我们现在把场景考虑的全面一点,对于复杂一点的系统,这个最大长度的限制可能来源很多,比如配制文件,数据库,可能类工作在前台比如web而配制在后台,可能需要和第三放系统一起工作而需要到第三方系统中获取而对方只提供web service...

这么一个简单的依赖,“用户名的最大长度”,如果用依赖注入,只要一个简单的setUsernameMaxLength()方法就可以搞定。考虑上面那么多种可能都出现,最恶劣的情况是要求一个系统可以同时支持然后通过配制方式进行,这对于将一个产品卖给n家客户的公司来说是最正常不过的要求。

那么我们来看一个很有"spring"风格的采用依赖注入的设计,通常都将会是这样:

注册工作类:
public void RegisterWork {
    public void setUsernameMaxLengthProvider(UsernameMaxLengthProvider provider) {
        int maxLength = provider.getUsernameMaxLength(); //简单获取结果,不管provider细节
    }
    ....
}
“用户名的最大长度”的提供者接口
public interfacd UsernameMaxLengthProvider {
    public int getUsernameMaxLength();
}
“用户名的最大长度”的提供者则可以有以下实现,都只负责读取数据,不关心数据被谁使用,怎么使用:
1.直接提供,可以用spring 构造函数方式注入usernameMaxLength值,也可以junit测试时直接new DirectdProvide对象
public class DirectdProvider implements UsernameMaxLengthProvider  {
    private int usernameMaxLength = 10;
    public int getUsernameMaxLength() {
        return UsernameMaxLength;
    }
    public DirectdProvider (int usernameMaxLength) {
        this.usernameMaxLength = usernameMaxLength;
    }
}
2.读本地配制文件
public class LocalConfigFileProvider implements UsernameMaxLengthProvider  {   
    public void read(File configFile) {
        usernameMaxLength = ....
    }
}
3.类似的从数据库读取 DatabaseProvide
4.类似的web service从第三方读取 WebServiceProvider
5.其他的可能扩展的方式

开发时逻辑清晰,代码可读性超强,基本看类名和函数名搞定。测试时,轻松测试RegisterWork,testcase中只要worker.setUsernameMaxLengthProvider(new DirectdProvider(20))就搞定。而针对UsernameMaxLengthProvider的几个实现类,更是轻松使用junit,每个都覆盖一遍。

呵呵,现在我们可以砍刀,最简单的一个int型的“用户名的最大长度”,都可能遭遇如此复杂的场景。如果不用倚赖注入,而是选择在RegisterWork中自己搞定“用户名的最大长度”的获取,那么可能要遇到以下问题:
1. RegisterWork极其复杂,可以想像类似的依赖肯定还有其他
2. 获取“用户名的最大长度”的方式和注册的业务处理逻辑完全没有直接联系,对注册过程来说它只关注结果,“用户名的最大长度”是10还是20,而不是到底读本地文件还是读数据库。喧宾夺主了,次要逻辑干扰了主要逻辑
3. 难于测试。获取“用户名的最大长度”的方式的这些代码,被藏在RegisterWork类中,而且很有可能是private方法不对外暴露(如果不依赖注入还需要暴露吗?暴露给谁呢),怎么用mock测试?怎么能保证以上几种的实现都覆盖到?
4. 难于扩展。就算上面都搞定了,某一天突然来了一个变态需求,要求用ldap从另一个地方取配置呢?难道再把ldap请求的那一大片代码也写到RegisterWork里面?
5. 更难于被第三方扩展。运气好,上面这个ldap取配制的变态需求客户开始没有要求。顺利开发完成测试通过然后准备上线,最后一晚了客户才发现,"哦,给忘了,你们想办法给加上,快,快,明天一早就要上线运行了...你们写死在代码里面了?那只能你们修改了原代码了"。吐血了吧,先骂一顿,可是活还的干啊,咬牙切齿的把新的实现代码加上了,还得编译打包更新重启...如果是spring多好,单独写一个LdapProvider类,测试(这个测试比杂在RegisterWork里面测试简单的多)通过后单独提供这个class仍classpath下,修改spring的配制将原来的***Provider替换掉,轻松搞定,甚至可以把这活仍给客户的开发人员,告诉他们怎么替换就可以了,管你ladp还是其他,谁让你们需求不明确,自己扩展去。
6. 容易出错。刚吐血完成上面的变态需求,更新完毕,一会客户电话来了,“...怎么...不正常了?”。又吐血几升地检查,终于找出来了,原来是刚才写ladp访问的代码时不小心改错了RegisterWork的一个地方,谁让RegisterWork类有几十上百个方法好几千行呢,一时急,又没有测试到......可是客户不会理解的。

上述的场景,spring + 依赖注入的设计方式,优点很明显吧。

再考虑一下维护和二次开发的问题,上面的spring + 依赖注入的代码,好看易懂,方便扩展,维护起来轻松。如果是那么堆在RegisterWork里面,在那个大堆中代码要找出这些代码并读懂,估计不是件轻松的事情。

代码维护是需要成本的,写出易于维护的代码,是一个优秀程序员的基本素养,至少,不能让下一个接手的人骂娘吧?
1
1
分享到:
评论
1 楼 liuzongan 2008-01-23  
维护起来轻松吗?那到未必,一旦多了性能肯定会出现问题的,维护起来并不是那么方便

相关推荐

    Spring 控制反转 依赖注入

    **Spring 框架中的控制反转 (IoC) 和依赖注入 (DI)** 在软件开发中,控制反转(Inversion of Control,简称IoC)是一种设计原则,它将对象的创建和管理权从代码中剥离出来,转交给一个外部容器(如Spring框架)。...

    Spring.Net IOC依赖注入原理流程解析

    本文将详细介绍Spring.Net IOC依赖注入原理流程解析,通过示例代码介绍了非常详细,对大家的学习或者工作具有一定的参考学习价值。 一、什么是IOC? IOC(Inversion of Control),即控制反转,不是一种技术,而是...

    spring2.5.6相关依赖jar包

    通过依赖注入,Spring可以自动为对象提供所需的依赖,无需手动创建和装配对象。这个版本的Spring还支持AOP(Aspect Oriented Programming,面向切面编程),允许开发者定义横切关注点,如日志、事务管理等,以提高...

    【原创】JDK1.8 教程,不用任何框架实现MVC架构和仿spring注入管理的例子

    总的来说,这个JDK1.8教程旨在帮助开发者理解MVC架构和依赖注入的核心概念,而无需依赖Spring框架。通过实践这些概念,开发者可以更好地掌握Java EE开发,并为将来学习和使用更高级的框架打下坚实的基础。同时,这也...

    spring4讲义-第二章spring与IoC

    本章主要介绍Spring框架中的控制反转(Inversion of Control,IoC)思想,以及依赖...学习Spring框架不仅是掌握一种开发技术,更重要的是理解控制反转和依赖注入等设计模式的思想,这在软件开发中有着广泛的应用价值。

    Spring技术内幕:深入解析Spring架构与设计原理[汇编].pdf

    * 依赖注入(Dependency Injection): Spring使用依赖注入来解耦合应用程序中的组件,提高系统的灵活性和可维护性。 * AOP(Aspect-Oriented Programming): Spring使用AOP来实现面向方面的编程,提高系统的可维护...

    设计模式实验报告-依赖注入.docx

    ### 设计模式实验报告——依赖注入 #### 一、实验目的与意义 依赖注入(Dependency ...依赖注入作为一种重要的设计模式,在现代软件开发中具有广泛的应用价值,能够有效提高代码的可读性、可维护性和可扩展性。

    spring-framework-5.3.20

    1. **Core Container**:核心容器包含Bean工厂(BeanFactory)和应用上下文(ApplicationContext),它们负责管理对象的生命周期和依赖注入。 2. **Data Access/Integration**:数据访问模块包括JDBC、ORM(Object-...

    Spring技术内幕:深入解析Spring架构与设计原理(第2版)+.pdf

    - **依赖注入**:Spring通过依赖注入的方式实现对象之间的解耦。依赖注入有三种主要方式:构造器注入、setter方法注入和字段注入。其中,构造器注入被认为是最为安全的方式之一,因为它能够在对象创建时就确保所有...

    Spring 5.2.9的IOC核心jar包

    Spring框架是Java后端开发中的一个关键组件,尤其在依赖注入(Dependency Injection,简称DI)和控制反转(Inversion of Control,简称IOC)领域,它扮演着至关重要的角色。Spring 5.2.9版本是该框架的一个稳定版本...

    spring-framework-3.0.5.RELEASE 资源包,包含文档包和依赖包

    1. **依赖注入(Dependency Injection, DI)**:这是 Spring 框架的核心特性之一,它允许我们通过外部容器来管理对象的创建和依赖关系,而非在代码中硬编码这些依赖。DI 可以提高代码的可测试性和可维护性。 2. **...

    Spring Framework v6.1.4.zip

    Core Container包括Bean工厂和ApplicationContext,它们是Spring的核心,负责管理应用对象的生命周期和依赖注入。Data Access/Integration模块则支持各种数据存取技术,如JDBC、ORM(对象关系映射)框架如Hibernate...

    spring的核心思想

    综上所述,Spring框架的核心思想在于通过控制反转和依赖注入等机制来实现对象间的解耦,从而提高软件系统的可维护性和可扩展性。此外,Spring框架还提供了强大的功能支持和广泛的整合能力,使其成为Java企业级应用...

    Spring.net实战开发

    一,课程介绍: Spring.NET+NHibnerte+ASP.NET MVC4: 一个良好的框架可以让开发人员减轻...Spring DOTNET 1.0 包含一个完全功能的依赖注入容器和AOP库。后续的发布将包含对ASP DOTNET、Remoting和数据访问的支持。

    spring和RMI分布式整合源码

    通过Spring的Bean工厂,我们可以将RMI服务声明为Spring Bean,这样就可以利用Spring的依赖注入来配置和服务。此外,Spring AOP可以用于在远程方法调用前后添加拦截逻辑,如日志记录、性能监控等。 具体到这个压缩包...

    Spring技术内幕:深入解析Spring架构与设计原理(第2版) .pdf

    Spring框架最初是为了简化企业应用开发而设计的,它提供了一种轻量级的方式来管理依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)。Spring的核心特性包括但不限于: 1. *...

    基于OSGi和Spring开发Web应用

    综上所述,基于OSGi和Spring开发Web应用不仅能够充分利用OSGi的模块化优势和Spring的依赖注入机制,还能借助dmServer和SpringSource应用平台等工具,实现更加高效、灵活和可靠的企业级应用开发。

    spring3框架 spring3框架

    Spring框架的核心特性包括依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)。依赖注入允许开发者通过配置文件或注解来管理对象之间的依赖关系,降低了代码的耦合度,提高了...

    spring2.0和2.5 reference的中文版

    Spring框架是Java开发中广泛应用的一个开源框架,以其强大的依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect-Oriented Programming,简称AOP)能力而著名。本压缩包包含的是Spring 2.0和2.5版本的...

Global site tag (gtag.js) - Google Analytics