Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 1174|回复: 0

Spring 基础知识

[复制链接]

该用户从未签到

发表于 2011-10-9 23:29:12 | 显示全部楼层 |阅读模式
此文章意在介绍反转模式(Inversion Of Control)的概念以及它是如何简化并更有效率的进行应用程序的设计。我们将察看IoC框架的不同类型。通过展示IoC能够带来更简单,更灵活的代码,你也将能够看到为什么IoC吸引了这么多的兴趣。



        IoC理论

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


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

public class JDBCDataManager {   
public void accessData() {   
DataSource dataSource = new DataSource();   
//access data   
       …   
}   
}   
   
  

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


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

public class JDBCDataManager {   
public void accessData() {   
DataSource dataSource = ApplicationResources.getDataSource();   
}   
}  




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



        Ioc框架

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

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



        注射接口(类型1)Interface Injection

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


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

import org.apache.avalon.framework.*;   
   
public class JDBCDataManger implements Serviceable {   
   DataSource dataSource;   
   public void service (ServiceManager sm)     
         throws ServiceException {   
     dataSource = (DataSource)sm.lookup("dataSource");   
   }   
      
   public void getData() {   
     //use dataSource for something   
   }   
}   



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

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



        设置器注射 Setter Injection(Type 2)

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


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

public class JDBCDataManger {   
private DataSource dataSource;   
     
public void setDataManager(DataSource dataSource ){   
   this.dataSource = dataSource;   
}   
     
public void getData() {   
     //use dataSource for something   
}   
}  



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


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

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




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


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

<bean id="dataManager"     
class="example.JDBCDataManger">   
<property name="dataSource">   
   <ref bean="myDataSource"/>   
</property>   
</bean>  




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



         构造函数注射 Constructor Injection(Type 3)

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


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

public class JDBCDataManger {   
private DataSource dataSource;      
public JDBCDataManger(DataSource dataSource) {   
   this.dataSource = dataSource;   
}   
     
public void getData() {   
     //use dataSource for something   
}   
}  
回复

使用道具 举报

该用户从未签到

发表于 2011-10-11 21:40:21 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-5-20 09:30 , Processed in 0.386153 second(s), 46 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表