控制反转IOC,这是个广义的概念,指将控制权交还给框架。具体实现由面向切面的AOP,依赖注入DI,等等.
依然注入(DI)是在任何需要依赖的代码不参与的情况下将应用程序连接在一起的一项技术。
<依赖注入(DI)是在ApplicationContext内部实现完成的,Spring的核心对象就是ApplicationContext(其主要功能创建对象和依赖注入)>
下面是个例子:
//接口1,定义收银机 public interface CashRegister{ //返回商品总价 public BigDicmal calTotalPrice(ShoppingCart cart); } //接口2,定义查询接口 public interface PriceMatrix{ //返回价格 public BigDicmal lookUpPrice(Item item); } //接口3 public class CashRegiterImpl implements CashRegister{ //priceMartix的实例 private PriceMatrix priceMartix=new PriceMatrix(); public BigDicmal calTotalPrice(ShoppingCart cart){ BigDicmal total=new BigDicmal("0.0"); for(Item item:cart.getItem()){ total.add(priceMartix.lookUpPrice(item)); } return total; } }
在这个例子中存在有3个问题:
1,每个CashRegisterImpl实例都有一个priceMatrix实例,若是创建以及维护的成本高,就是在浪费资源,对于开销很大的服务应该多个客户共享一个实例。
2,CashRegisterImpl知道了PriceMatrix的实现细节。通过显示的创建PriceMatrix实例,使得CashRegisImpl和PriceMatrix紧密的联系在一起。
3,与实现类紧密结合的结果是编写测试类比较困难。编写测试单元应当在脱离外部环境资源的情况下运行。如果要测试接口3,则需要选择一个完成运作的PriceMartixImpl
使用依赖注入进行改造:
//接口1,定义收银机 public interface CashRegister{ //返回商品总价 public BigDicmal calTotalPrice(ShoppingCart cart); } //接口2,定义查询接口 public interface PriceMatrix{ //返回价格 public BigDicmal lookUpPrice(Item item); } //接口3 public class CashRegiterImpl implements CashRegister{ //priceMartix private PriceMatrix priceMartix; //方式一:设置setter注入 public setPriceMartix(PriceMatrix _priceMartix){ this.priceMartix=_priceMartix } //方式二:设置构造器注入 public CashRegisterImpl(PriceMartix _priceMartix){ this.priceMartix=priceMartix; } public BigDicmal calTotalPrice(ShoppingCart cart){ BigDicmal total=new BigDicmal("0.0"); for(Item item:cart.getItem()){ total.add(priceMartix.lookUpPrice(item)); } return total; } }移除priceMartix依赖的显示实例化,通过将此依赖移除,他可以很容易的被共享使用。也有利于做单元测试化。
依然注入的一个优势是客户并不知道依赖的具体实现,换言之就是客户代码并没有耦合到具体的实现中来。
在来张图片。比较清晰: