Type 接口注入
我们常常借助接口来将调用者与实现者分离如:
public class ClassA {
private InterfaceB clzB;
public init() {
Ojbect obj =
ClassforName(ConfigBImplementation)newInstance();
clzB = (InterfaceB)obj;
}
……
}
上面的代码中ClassA依赖于InterfaceB的实现如何获得InterfaceB实现类的实例?传统的方法是在代码中创建InterfaceB实现类的实例并将起赋予clzB
而这样一来ClassA在编译期即依赖于InterfaceB的实现为了将调用者与实现者在编译期分离于是有了上面的代码我们根据预先在配置文件中设定的实现类的类名动态加载实现类并通过InterfaceB强制转型后为ClassA所用
这就是接口注入的一个最原始的雏形
而对于一个Type型IOC容器而言加载接口实现并创建其实例的工作由容器完成如JEE开发中常用的Contextlookup(ServletContextgetXXX)都是Type型IOC的表现形式
Apache Avalon是一个典型的Type型IOC容器
Type 构造子注入
构造子注入即通过构造函数完成依赖关系的设定如
public class DIByConstructor {
private final DataSource dataSource;
private final String message;
public DIByConstructor(DataSource ds String msg) {
thisdataSource = ds;
ssage = msg;
}
……
}
可以看到在Type类型的依赖注入机制中依赖关系是通过类构造函数建立容器通过调用类的构造方法将其所需的依赖关系注入其中
PicoContainer(另一种实现了依赖注入模式的轻量级容器)首先实现了Type类型的依赖注入模式
Type 设值注入
在各种类型的依赖注入模式中设值注入模式在实际开发中得到了最广泛的应用(其中很大一部分得力于Spring框架的影响)
在笔者看来基于设置模式的依赖注入机制更加直观也更加自然Quick Start中的示例就是典型的设置注入即通过类的setter方法完成依赖关系的设置
SpringFrameWork Developers Guide Version
September So many open source projects Why not Open your Documents?
几种依赖注入模式的对比总结
接口注入模式因为具备侵入性它要求组件必须与特定的接口相关联因此并不被看好实际使用有限
Type和Type的依赖注入实现模式均具备无侵入性的特点在笔者看来这两种实现方式各有特点也各具优势(一句经典废话?)
Type 构造子注入的优势
在构造期即创建一个完整合法的对象对于这条Java设计原则Type无疑是最好的响应者
我的理解就是你要通过一种方式来保证对象的引用完整性type选择了构造器的方式来实现
避免了繁琐的setter方法的编写所有依赖关系均在构造函数中设定依赖关系集中呈现更加易读
我的理解使用构造方法就不需要每个属性都写set和get方法了这样省去了很多的代码
由于没有setter方法依赖关系在构造时由容器一次性设定因此组件在被创建之后即处于相对不变的稳定状态无需担心上层代码在调用过程中执行setter方法对组件依赖关系产生破坏特别是对于Singleton模式的组件而言这可能对整个系统产生重大的影响
我的理解使用构造器来实现那么你需要一次对所有的属性都初始话相对set方法来说缺少了一些灵活性
同样由于关联关系仅在构造函数中表达只有组件创建者需要关心组件内部的依赖关系对调用者而言组件中的依赖关系处于黑盒之中对上层屏蔽不必要的信息也为系统的层次清晰性提供了保证
我的理解 spring的这设计就是要屏蔽依赖关系你只需要对接口编程而不需要考虑依赖关系的实现所以对调用者来说依赖关系是处于黑盒当中
通过构造子注入意味着我们可以在构造函数中决定依赖关系的注入顺序对于一个大量依赖外部服务的组件而言依赖关系的获得顺序可能非常重要比如某个依赖关系注入的先决条件是组件的DataSource及相关资源已经被设定
我的理解关于顺序问题我们来看以下两段代码
public DIByConstructor(DataSource ds String msg) {
thisdataSource = ds;
ssage = msg;
}
public DIByConstructor(DataSource ds String msg) {
thisdataSource = ds;
ssage = msg;
}
在本例中顺序不太重要但是如果message的初始化需要用到datasource 的话那么就必须要先初始化datasource所以相对来说顺序就是确定了
Type 设值注入的优势
对于习惯了传统JavaBean开发的程序员而言通过setter方法设定依赖关系显得更加直观更加自然
如果依赖关系(或继承关系)较为复杂那么Type模式的构造函数也会相当庞大(我们需要在构造函数中设定所有依赖关系)此时Type模式往往更为简洁
我的理解依赖关系(或继承关系)较为复杂指的是属性较多需要写很多的set和get方法
对于某些第三方类库而言可能要求我们的组件必须提供一个默认的构造函数(如Struts中的Action)此时Type类型的依赖注入机制就体现出其局限性难以完成我们期望的功能
可见Type和Type模式各有千秋而SpringPicoContainer都对Type和Type类型的依赖注入机制提供了良好支持这也就为我们提供了更多的选择余地理论上以Type类型为主辅之以Type类型机制作为补充可以达到最好的依赖注入效果不过对于基于Spring Framework开发的应用而言Type使用更加广泛