Spring揭秘——什么是IOC和DI

一、IoC的基本概念

IoC全称Inversion of Control,即控制反转。它的核心技术是DI (Dependency Injection),即依赖注入。
什么是IOC?打个比方,我们要做一个系统,为客户提供股票新闻。通常我们需要从不同的新闻社订阅新闻来源,然后通过批处理程序定时到指定的新闻服务器抓取最新的股票新闻,接着保存数据库,最后在前端显示。代码如下:

public class FXNewsProvider
{
	private IFXNewsListener newsListener;
	private IFXNewsPersister newPersistener;
	public void getAndPersistNews()
	{
		String[] newsIds = newsListener.getAvailableNewsIds();
		if(ArrayUtils.isEmpty(newsIds))
			{
			return;
			}
				for(String newsId : newsIds)
				{
				FXNewsBean newsBean = newsListener.getNewsByPK(newsId);
				newPersistener.persistNews(newsBean);
				newsListener.postProcessIfNecessary(newsId);	
			}
	}
}

其中, FXNewsProvider 需要依赖 IFXNewsListener 来帮助抓取新闻内容,并依赖 IFXNews-
Persister 存储抓取的新闻。
假设默认使用道琼斯(Dow Jones)新闻社的新闻,那么我们相应地提供了 DowJonesNewsLis-
tener 和 DowJonesNewsPersister 两个实现。通常情况下,需要在构造函数中构造 IFXNewsProvider
依赖的这两个类:

public FXNewsProvider() {
        this.newsListener = new DowJonesNewsListener();
        this.newPersistener = new DowJonesNewsPersister();
    }

以往,如果我们依赖于某个类或服务,最简单而有效的方式就是直接在类的构造函数中新建相应的依赖类。我们都是自己主动地去获取依赖的对象!
IoC则是在我们需要时将某个依赖对象送过来,它的反转,就反转在让你从原来的事必躬亲,转变为现在的享受服务。

二、依赖注入

被注入对象又是通过哪些什么来通知IoC为其提供适当服务的呢?其实就是依赖注入!依赖注入主要有两种方式:1、构造方法注入;2、setter方法注入

2.1 构造方法注入

顾名思义,构造方法注入,就是被注入对象可以通过在其构造方法中声明依赖对象的参数列表,让IoC容器知道它需要哪些依赖对象。对于前面例子中的 FXNewsProvider 来说,只要声明如下构造方法即可支持构造方法注入。

public FXNewsProvider(IFXNewsListener newsListner,IFXNewsPersister newsPersister)
{
	this.newsListener = newsListner;
	this.newPersistener = newsPersister;
}

IoC会检查被注入对象的构造方法,取得它所需要的依赖对象列表,进而为其注入相应的对象。同一个对象是不可能被构造两次的,因此,被注入对象的构造乃至其整个生命周期,应该是由IoC来管理的。构造方法注入方式比较直观,对象被构造完成后,即进入就绪状态,可以马上使用。

2.2 setter 方法注入

当前对象只要为其依赖对象所对应的属性添加setter方法,就可以通过setter方法将相应的依赖对象设置到被注入对象中。以 FXNewsProvider 为例,添加setter方法后如下所示。

public class FXNewsProvider
{
	private IFXNewsListener newsListener;
	private IFXNewsPersister newPersistener;
	public IFXNewsListener getNewsListener() {
		return newsListener;
	}
	public void setNewsListener(IFXNewsListener newsListener) {
		this.newsListener = newsListener;
	}
	public IFXNewsPersister getNewPersistener() {
		return newPersistener;
	}
	public void setNewPersistener(IFXNewsPersister newPersistener) {
		this.newPersistener = newPersistener;
	}
}

这样,外界就可以通过调用 setNewsListener 和 setNewPersistener 方法为 FXNewsProvider 对象注入所依赖的对象了。
setter方法注入虽不像构造方法注入那样,让对象构造完成后即可使用,但相对来说更宽松一些,可以在对象构造完成后再注入。

2.3 两种注入方式的比较

构造方法注入的优点就是,对象在构造完成之后,即已进入就绪状态,可以马上使用。缺点就是,当依赖对象比较多的时候,构造方法的参数列表会比较长。而通过反射构造对象的时候,对相同类型的参数的处理会比较困难,维护和使用上也比较麻烦。而且在Java中,构造方法无法被继承,无法设置默认值。对于非必须的依赖处理,可能需要引入多个构造方法,而参数数量的变动可能造成维护上的不便。

setter方法注入因为方法可以命名, 所以setter方法注入在描述性上要比构造方法注入好一些。
另外,setter方法可以被继承,允许设置默认值,而且有良好的IDE支持。缺点当然就是对象无
法在构造完成后马上进入就绪状态。

三、IOC的优点

不使用IOC看上去照样可以实现功能,但是如果需求发生变化了,比如需求追加了处理另一家新闻社的新闻来源时,问题就来了。因为我们之前没有用IoC,所以,现在的对象跟 DowJonesNewsListener 是绑定
的,我们无法重用这个类了。
而使用IoC后,我们却完全可以不做任何改动,因为不管是DowJones还是MarketWin24,对于我们的系统来说,处理逻辑实际上应该是一样的。因此,我们只要根据MarketWin24的新闻服务接口,为MarketWin24的 FXNewsProvider 提供相应的 MarketWin24NewsListener 注入就可以了,见以下代码:

FXNewsProvider dowJonesNewsProvider =new FXNewsProvider(new DowJonesNewsListener(),new DowJonesNewsPersister());
...
FXNewsPrivider marketWin24NewsProvider =new FXNewsProvider(new MarketWin24NewsListener(),new DowJonesNewsPersister());
...

IoC是一种可以帮助我们解耦各业务对象间依赖关系的对象绑定方式!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值