`
isiqi
  • 浏览: 16043691 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论
阅读更多
此文章意在介绍反转模式(InversionOfControl)的概念以及它是如何简化并更有效率的进行应用程序的设计。我们将察看IoC框架的不同类型。通过展示IoC能够带来更简单,更灵活的代码,你也将能够看到为什么IoC吸引了这么多的兴趣。

IoC理论

描述IoC是什么和它能提供什么的最佳方式就是看一些简单的例子。下面的JDBCDataManager类是用于管理应用程序对于数据库的访问。这个应用程序使用未加工的JDBC最为持久层方案。为了通过JDBC访问持久层,JDBCDataManager需要一个DataSource对象。标准途径是硬编码DataSource对象到类中,像这样:


代码:
--------------------------------------------------------------------------------

publicclassJDBCDataManager{
publicvoidaccessData(){
DataSourcedataSource=newDataSource();
//accessdata

}
}





JDBCDataManager正在处理着我们应用程序中所有的数据访问,硬编码DataSource不是很坏,但是我们可能想更抽象DataSource,或许通过某种系统属性对象得到它:


代码:
--------------------------------------------------------------------------------

publicclassJDBCDataManager{
publicvoidaccessData(){
DataSourcedataSource=ApplicationResources.getDataSource();
}
}





在任意一种情况下,JDBCDataManager不得不自己去得到DataSource。
IoC采取了不同的方式-使用IoC,JDBCDataManager将声明它对于一个DataSource的需要,IoC框架会来提供一个。这意味着组件将不再需要知道如何得到依赖的东西,也就带来了更简洁,更聚焦,更灵活的代码。

Ioc框架

IoC背后的思想不是很新;实际上,IoC只是依赖注射原DependencyInversionPrinciple的新缩写。对于IoC的兴趣是它的新东西,还有就是大量框架开始进行实际开发来辅助IoC的使用。

IoC框架也是IoC模式的催化物-框架的工作,就是在IoC系统中连接组建的粘合剂。当IoC的普遍原理被普遍接受时,在众多框架中就开始有着明确的几种各自不同的实现。PicoContainer的开发者最初定义了三种IoC的类型,是为了区分当时其他框架的实现途径。首先,这些类型被简单的叫做Type1,2和3,但是MartinFowler文章中,InversionofControlContainersandtheDependencyInjectionPattern他对于这三种类型指定了更有含义的术语,这些我们将在在下面使用。
在文章的剩下部分,我们简要的查看Avalon,然后更加深入讨论两种流行的IoC框架,Spring和PicoContainer,他们都提供的IoC类型。

注射接口(类型1)InterfaceInjection

使用IoC注射接口,组件需要实现容器提供的特殊接口以便被配置。让我们察看一下使用Avalon框架对于JDBCDataManager的重构:


代码:
--------------------------------------------------------------------------------

importorg.apache.avalon.framework.*;

publicclassJDBCDataMangerimplementsServiceable{
DataSourcedataSource;
publicvoidservice(ServiceManagersm)
throwsServiceException{
dataSource=(DataSource)sm.lookup("dataSource");
}

publicvoidgetData(){
//usedataSourceforsomething
}
}





这种形式的IoC已经广为应用,比IoC这个术语使用的时间还长?大多数读者或许早就使用过这种形式的IoC,例如,当使用EJB框架时。你的组件扩展和实现了特定接口,这是他们被框架自身调用。

Avalon框架事实上,已经提供了IoC框架很多年了,并没有像Spring和PicoContainer任何一者那样流行,很可能是由于这种实现途径的弊端。实现特殊接口的条件就是使得代码感觉臃肿,同时也使你的应用与框架耦合起来。下面的两种IoC提供的好处远远超过这种IoC形式。

设置器注射SetterInjection(Type2)

使用IoC的Setter注射,一些外部元数据被用于解决依赖性问题。在Spring中,这种元数据采取了XML配置文件的形式。使用这种形式的IoC,JDBCDataManager类看起来像普通的bean:


代码:
--------------------------------------------------------------------------------

publicclassJDBCDataManger{
privateDataSourcedataSource;

publicvoidsetDataManager(DataSourcedataSource){
this.dataSource=dataSource;
}

publicvoidgetData(){
//usedataSourceforsomething
}
}





我们的JDBCDataManager组件暴露了它的dataSource属性来允许Spring设置它。Spring通过XML配置这样做。那么,我们首先定义了一个数据源bean(可以被多个组件重用)


代码:
--------------------------------------------------------------------------------

<beanid="myDataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<propertyname="driverClassName">
<value>com.mydb.jdbc.Driver</value>
</property>
<propertyname="url">
<value>jdbc:mydb://server:port/mydb</value>
</property>
<propertyname="username">
<value>root</value>
</property>
</bean>





接下来,我们定义一个管理器(数据管理器)的实例并将数据源引用传递给它:


代码:
--------------------------------------------------------------------------------

<beanid="dataManager"
class="example.JDBCDataManger">
<propertyname="dataSource">
<refbean="myDataSource"/>
</property>
</bean>





在运行时,JDBCDataManager类将使用正确的DataSource依赖引用来实例化,然后我们将能够通过Spring框架本身来访问该bean。
这种依赖关系的定义使得单元测试简单很多:为假设的仿制对象简单的定义一个XML文件,代替正常的XML文件,然后就可以测试了。
或许Setter注射的最大好处就是应用程序代码不需要以任何方式绑定到容器上,但是这也有弊端?不能马上清楚地知道JDBCDataManager组件与其他一切的关系。看起来好像DataSource被神奇般的传递给JDBCDataManager,正如依赖管理器在Java代码以外完成这些事情。另外的缺点是Spring需要getters和setters来它的依赖决定。你必须暴露你或许不想暴露的,潜在地破坏了数据封装原则,至少,使得类的接口比你需要的更复杂些。Spring的元数据被描述到XML中,在普通的Java编译阶段的编译期不能验证他们,意味着那些坏掉的依赖性情况只能在运行期才能被看出。

构造函数注射ConstructorInjection(Type3)

构造器注射基本上基于”好市民”GoodCitizen的原理。好市民模式由JoshuaBloch提出的,来描述对象在创建时就完全的设置好并进行了使用需要的验证。实践中,这意味着,在实例化后,对象不需要对他们调用更多的方法,来保证他们的可用性。也就是说,你能够确保在你创建了对象后,就可以使用。这从根本上简化了你的代码并降低了编写防御性检查的代码,同时你的代码在整体上更加具有防御性(moredefensive)。这样的代码也更容易测试。
使用构造器注射,你要注册一个对象到框架中,通过指定参数来使用(能够被框架依次创建)并在此时请求一个实例。被注册的组件必须实现一个构造器,这个构造器得是能够用来进行注射依赖内容的。最近,Spring已经开始支持这种IoC形式,但是我们而是去察看PicoContainer,它就是建立在这种原理之上的框架。察看JDBCDataManager,现在使用构造器注射框架对其重新编码。


代码:
--------------------------------------------------------------------------------

publicclassJDBCDataManger{
privateDataSourcedataSource;
publicJDBCDataManger(DataSourcedataSource){
this.dataSource=dataSource;
}

publicvoidgetData(){
//usedataSourceforsomething
}
}





不是使用一个配置文件,PicoContainer而是使用一些旧貌换新颜的Java代码来将一切粘合在一起:
//创建一个datasourcebean


代码:
--------------------------------------------------------------------------------

BasicDataSourcedataSource=newBasicDataSource();
dataSource.setDriverClassName(“com.mydb.jdbc.Driver”);
dataSource.setUrl(“jdbc:mysql://localhost:3306/mydb”);
dataSource.setUsername(“Bob”);

//创建容器
MutablePicoContainerpico=newDefaultPicoContainer();

//registercomponentswithcontainer
ConstantParameterdataSourceParam=newConstantParameter(dataSource);
Stringkey=“DataManager”;
Parameter[]params={dataSourceParam};
/*
*NoweachrequestforaDataManagerwillinstantiate
*aJDBCDataManagerobjectwithourdefined
*dataSourceobject
*/
pico.registerComponentImplemention(key,JDBCDataManager.class,parems);
  1. 为了获得JDBCDataManager对象的实例,我们不得不通过它的key来引用这个类:
  2. [code]
  3. JDBCDataManagerdm=(JDBCDataManager)pico.getComponentInstance(key);
  4. 像Setter注射的IoC,我们的应用程序代码(除了Pico特定的配置之外),是独立于框架本身的,并给你带来了使用”好市民”模式的继承来的优势。另外,PicoContainer只需要一个构造函数,我们只需要做很少的准备工作来使用IoC框架相对于Setter注射IoC。
  5. 这种方式的潜在问题在于在使用继承时,去维护它的依赖性会变得较复杂,并且他会引起一些事情当你使用构造器来完成一些别的事情而并非简单的实例化对象时。
  6. IoC实践:TheDataAccessObjectPattern
  7. 目前,我们的JDBCDataManger类使用SQL来取得我们的数据。假如我们想要通过Hibernate访问数据或者JDO?我们可以使用一个新类来替换JDBCDataManager的使用,但是更好的方案是使用数据访问对象(DAO)模式。概要来说,DAO模式定义了一种方法使得普通的值对象可以用来进行设置和取得数据(考虑普通的JavaBeans),并且通过一个抽象数据访问对象来完成的。(ForthoseofyouwishingtolearnmoreontheDAOpattern,Sun'sPatternCatalogisagoodplacetostart.)
  8. 我们存在的JDBCDataManager将保持不变。我们将添加DataManager的接口,它将实现我们数据访问的方法。出于对争论的考虑,我们也添加Hibernate的实现,HibernateDataManager。JDBCDataManager和HibernateDataManager都开始数据访问对象。
  9. 假设我们已经使用了IoC,改变为使用DAO是很简单的事情。假定我们使用上面的Spring代码,我们能够使用Hibernate代替JDBC通过XML配置来由HibernateDataManager处理而不是JDBCDataManager类。在切换DAO实现的时候,我们的应用程序代码将保持不变,假设他们是期待DataManager接口而不是一个JDBCDataManager实现。
  10. 通过使用两种实现来使用DAO接口,我们正在合并DAO模式与抽象工厂模式AbstractFactorypattern。效果上,IoC框架承担了工厂本身的角色。开发过程中,使用这样一个模式使得移动到另外的持久机制的确很容易,并且它对于你的开发环境上做很小的设置相对于你在发布环境上做设置,大有好处。DataManager的两种实现可以是同样的代码基准,这样切换他们是微不足道的。
  11. Spring对比PicoContainer
  12. PicoContainer和Spring细微不同在于设置你的IoC绑定所需的工作。Spring能够被配置要不需要一个XML配置文件或者直接通过Java,然而PicoContainer需要一个Java的绑定(即使PicoExtras项目提供了XML配置支持)。我迅速的得出结论XML配置文件开始过渡使用(正如某人最近指出的,所有这些不同的配置文件几乎开始成为他们自己的一种新的语言),尽管哪种方式更好只是个人胃口问题。假如你需要多种配置(比如,一个对于开发,另外一个对于发布),一个基于XML的系统可能更好的,这只是对于配置管理。
  13. 两者都是轻型框架?他们可以与其他框架工作很好并具有不必与他们耦合的添加优势。PicoContainer是目前为止两者中较小的一个;它着手于IoC框架并不没有提供支持的类来与外部产品像Hibernate一起工作。值得注意的是Spring不只是一个IoC框架:它还提供了web应用和AOP框架,同时还有一些普遍的支持类,这些显著的增加了库德大小。个人意见,我发现Spring的web应用框架非常灵活。然而,它看起来在配置方面需要更多相比于Struts框架,并且至今还没有一套丰富的支持类。另外,AOP特色仍旧在开发,但是你或许不期待它成为纯的AOP框架例如AspectWerkz或者AspectJ.
  14. 如果你打算使用Spring提供的以外的类,你会发现它是很好的选择。如果,当然,你乐于自行实现这些(或者依赖外部项目来提供他们)这时Pico的小窍或许是一个决定的因素。两者都支持构造器IoC注射,但是仅仅Spring支持Setter注射?如果你更喜欢setter注射,那么Spring是首先。
  15. 结论
  16. 希望我已经展示了通过在您的应用中使用IoC,你可以获得整洁和更灵活的代码。Spring和PicoContainer能够简单的被引入到现有的项目作为正在重构工作的一部分,并且他们的引入促进了日后的重构工作。那些从开头就采取了IoC的项目将发现他们的应用程序代码将更容易定义内部组件的关系,并且将可以被更灵活
分享到:
评论

相关推荐

    spring的概要介绍与分析

    Spring框架的核心特性包括控制反转(IOC)和面向切面编程(AOP)。通过IOC,Spring容器负责对象的创建、配置和依赖注入,从而降低了代码的耦合度,提高了可维护性。AOP则允许开发者在不影响业务逻辑代码的情况下,...

    第四课:IOC容器设计理念与源码解读 (2)1

    1. IOC核知识点回顾 2. IOC 设计原理 1. Ioc理念概要 2. 实体Bean的创建 3. Bean的基本特性 4. 依赖注 2. 构造法注

    45页智慧城市IOC智慧运营中心平台整体解决方案2022.pptx

    内容概要:智慧城市通过物联网基础设施、云计算基础设施、地理空间基础设施等新一代信息技术以及维基、社交网络、Fab Lab、Living Lab、综合集成法、网动全媒体融合通信终端等工具和方法的应用,实现全面透彻的感知...

    生产实习概要

    微波技术基础总结 电磁场靶向调控技术技术优势 卅三先生的工程电磁场讲座.EEm04——电势能001 卅三先生的工程电磁场讲座.EEm04——电势能002 AOP技术基础 Spring IoC(控制反转)【IoC的技术基础】

    swiftsuspenders, AS3的快速轻重量IoC容器.zip

    swiftsuspenders, AS3的快速轻重量IoC容器 SwiftSuspenders注意:这个自述文件只是为了防止你阅读严重过时的一个用于 Swiftsuspenders 1.x 。这就是说,这里是一个非常快速的版本和API新功能的概要:特性使用标准化...

    spring学习笔记(有代码有注解解释)

    内容概要:学习Spring的一些学习笔记,主要学习Spring 框架两大核心机制(IoC、AOP) 笔记大纲:阅读笔记可以学习了解一下内容 如何使用 IoC ;配置文件;IoC 底层原理;通过运行时类获取 bean;通过有参构造创建 ...

    1、spring源码解析之概况流程

    跟踪源码进入ioc 概要 ​ 以前总是很忙,没有时间写博客,现在挤出时间写一些总结性及实用性的博客。 ​ 首先聊一下,之所以开始看源码,是因为随着自身对java的理解不断加深,感觉自己对技术架构方面很感兴趣。...

    东莞市大岭山镇数据智脑建设项目.pdf

    东莞市大岭山镇数据智脑建设项目.pdf

    2021年智慧城市之智能运行中心(IOC)解决方案48页.pptx

    内容概要:智慧城市通过物联网基础设施、云计算基础设施、地理空间基础设施等新一代信息技术以及维基、社交网络、Fab Lab、Living Lab、综合集成法、网动全媒体融合通信终端等工具和方法的应用,实现全面透彻的感知...

    api-algafood:涵盖了Spring Rest专家课程(进行中)技术。 Spring和依赖注入使用针对REST API的主要Spring生态系统项目,例如Spring Framework,Spring MVC,Spring Boot,Spring Data JPA,Spring Security OAuth和Spring HATEOAS。 还了解依赖注入如何与Spring,IoC容器,具有@ Component,@ Configuration和@Bean的bean定义,注入点,与@ Primary

    api-藻类食品 涵盖了Spring Rest专家课程(进行中)... 使用Spring概要文件,按概要文件配置application.properties,属性@Value和@ConfigurationProperties。 带有OpenAPI的JPA,Hibernate和Flyway域驱动设计(DDD)文

    基于JavaWeb的物业管理系统

    内容概要:通过带着读者编写servlet + jsp ,了解 servlet 核心原理。在手写项目的过程中会摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC、AOP、Bean生命周期、上下文、作用域、资源处理等...

    Apifox-windows-latest

    内容概要:通过带着读者手写简化版Spring框架,了解Spring核心原理。在手写Spring源码的过程中会摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC, AOP、 Bean生命周期、上下文、作用域、资源处理等...

    期末课设,基于·Android·开发

    内容概要:通过带着读者手写简化版 Spring 框架,了解 Spring 核心原理。在手写Spring 源码的过程中会摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC、AOP、Bean生命周期、上下文、作用域、...

    该项目是gradle+springboot+freemarker的项目,是对学生基本信息的增删改查。

    内容概要:通过带着读者手写简化版 Spring 框架,了解 Spring 核心原理。在手写Spring 源码的过程中会摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC、AOP、Bean生命周期、上下文、作用域、...

    Video基础知识简介

    内容概要:通过带着读者手写简化版 Spring 框架,了解 Spring 核心原理。在手写Spring 源码的过程中会摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC、AOP、Bean生命周期、上下文、作用域、...

    【基于java-ssm】大学生兼职论坛管理系统实现源码+lw+部署文档+讲解

    内容概要:该资源将通过手写简化版的 Spring 框架来深入理解 Spring 的核心原理。在实现过程中,将提炼出 Spring 框架的核心逻辑,简化代码实现过程,保留重要功能,例如:IOC(控制反转)、AOP(面向切面编程)、...

    SSM+课程设计+项目源代码+thymleaf

    内容概要:通过带着读者手写简化版 Spring 框架,了解 Spring 核心原理。在手写Spring 源码的过程中会摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC、AOP、Bean生命周期、上下文、作用域、...

    maven3.6.3.zip

    内容概要:通过带着读者手写简化版Spring框架,了解Spring核心原理。在手写Spring源码的过程中会摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC, AOP、 Bean生命周期、上下文、作用域、资源处理等...

    apache-tomcat-8.0.32

    内容概要:通过带着读者手写简化版Spring框架,了解Spring核心原理。在手写Spring源码的过程中会摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC, AOP、 Bean生命周期、上下文、作用域、资源处理等...

Global site tag (gtag.js) - Google Analytics