1,存在的问题?FX(foreign exchange)
例子:
一个第三方(外汇)新闻客户端FX,它要实时的获得新闻。
订阅新闻,然后通过批处理程序定时的到指定的新闻服务器抓取最新的外汇新闻,
接着将这些新闻存入本地数据库。最后从数据库调出数据显示在前台界面。
代码:
public class FXnewProvider {
private FxNewsListener newsListener;
private FxNewsListener newsPersister;
public FXnewProvider() {
newsListener = new SinaNewsListener();
newsPersister = new SinaNewsListener();
}
}
FXnewProvider需要依赖newsListener来帮助抓取新闻。
并且依赖newsPersister来存储抓取的新闻。
假设默认订阅的是SIna新闻,那么就需要在构造方法中实现。
问题:
1,直接获取对象的方法和希望有的理想状态?
直接获取对象的方法:通常我们需要某个类的服务时候,直接new一个对象(或者用service-locator解决之际的依赖耦合),然后直接就调用。
希望有的理想状态:但是上面的两种方式,都是我们主动地去获取需要的服务。(主动获取依赖的对象)我们理想的状态是不管这个对象是自己来,还是别人送来,我们只要需要时候能主动来就行。
2,设计的最基本要求?
所以我们的要求就是:让别人主动为我们服务。
3,如何设计的,实现的思想,以及和直接new对比?(我将注入对象 变成被服务对象)
通常情况下,被服务的对象会直接依赖于被依赖对象。(new方式)
但是在Ioc的场景中,二者之间通过设计出来的ioc service provider 来打交道,所有的被服务对象和被依赖对象现在由ioc service provider统一管理。
为什么叫IOC呢?
从被服务对象角度看,以前是主动调用被依赖对象。现在获取以来对象的方式发送了反转,并且控制也从被服务对象转到IOC service provider。
Ioc service provider,就是我们设计的主动为我们服务的人。
4,Ioc的定义?
本质上我们是要获得服务。现在的问题是如何获取服务。
获取服务的本质还是要获取依赖对象。现在的问题是如何获取依赖对象。
获取依赖对象的本质是在服务对象中定义好依赖对象变量。现在问题是在哪定义依赖对象变量。
4,在哪定义依赖对象的变量,实现设计的思想?
(1)构造函数中(注入):
设计的思想:
被服务对象通过在其构造方法中声明依赖对象做参数。让外部(通常是IOC容器)知道它需要那些依赖对象。
IOC service provider会检查被服务对象的构造方法,取得它所需要的依赖对象,进而注入到服务对象。
对象没有销毁之前,同一个对象不可能被构造两次,所以被服务对象的整个生命周期都是由IOC service provider管理。
代码:
public class FXnewProvider{
public FXnewProvider(FxNewsListener newsListner,FxNewsPersister newsPersister) {
this.newsListner = newsListner;
this.newsPersister = newsPersister;
}
}
(2)Setter和getter方法注入():(setter是更改对象的属性,getter是获得对象的属性)
设计思想:
外界调用setter方法注入。(也可以主动NEW方式)
通过setter更改对象的属性,getter获得对象的属性。
在对象构造完成之后调用setter方法注入
public class FXnewProvider{
private FxNewsListener newsListener;
private FxNewsPersister newsPersister;
public FxNewsListener getNewsListener(){
return newsListener;
};
public void setNewsListener(FxNewsListener Listner){
this.newsListener = Listener;
}
public FxNewsPersister getNewsPersister(){
return newsPersister;
};
public void setNewsPersister(FxNewsPersister Persister){
this.newsPersister = Persister;
}}
(3)接口注入
如果想用IOC service provider 注入,就需要实现接口,接口中方法参数是依赖类的变量。
只要被服务对象实现该接口,就可以得到依赖对象的变量。
从上面对比发现:设计的目的是不需要再new,而是IOC service provider直接传进来对象。
5,三种注入方式的比较?
接口注入:不提倡。
构造方法注入:缺点:当依赖对象比较多的时候,构造方法的参数列表会比较长,而通过反射构造对象的试试,对相同类型的参数的处理会比较困难,维护和使用上也比较麻烦,而且在java中构造方法无法被继承,无法设置默认值。对于非必须的依赖处理,可能需要引入多个构造方法,而参数数量的变动可能造成维护上的不便。
Setter方法注入:因为方法可以命名,所以setter方法注入在描述性比构造方法注入好些,setter方法可以被继承,允许设置默认值,而且有良好的ID E支持。缺点当然就是对象无法在构造完成后马上进入就绪状态。