IOC是spring的最基础部分,也是核心模块,Spring的其他组件模块和应用开发都是以它为基础的。IOC把spring的面向接口编程和松耦合的思想体现的淋漓尽致。
IOC概念
IOC(Inversion of Control)译为中文“控制反转”,许多应用都是由两个或更多个类通过彼此合作来实现业务逻辑的,这使得每个对象都要引用其合作对象(也就是它所以来的对象)来装配在一起工作,而这个装配过程如果靠硬编码来实现,他们之间的耦合性有多强就可想而知的。如果把这个装配过程交给第三方(如IOC容器)来实现,那么就能很好的解耦,此时控制就反转了,反转给了第三方(如IOC容器)。
IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:
- 依赖查找(Dependency Lookup):容器提供回调接口和上下文环境给组件。EJB和Apache Avalon都使用这种方式。
- 依赖注入(Dependency Injection):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。
Dependency Injection是时下最流行的IoC类型,所以有时我们说IOC的另一个名字叫依赖注入,它又有接口注入(Interface Injection),设值注入(Setter Injection)和构造子注入(Constructor Injection)三种方式。
IOC与旧方式的对比
本文Demo想实现的效果:架设需要之前是使用的MySql数据库,但后来却要转向Oracle数据,我们来看下使用IOC和不使用IOC的对比。当然这个例子并不合适,因为你可能立马想到Hibernate,所以请不要介意,这只是个Demo。
- 没有使用注入方式
package net.oseye;public class App { public static void main( String[] args ) { //调用数据库操作 new MysqlHelper().insert(); }}/** * Mysql数据库操作 */class MysqlHelper{ /** * 插入数据 */ public void insert(){ System.out.println("Mysql数据库插入操作"); }}
package net.oseye;public class App { public static void main( String[] args ) { //调用数据库操作 new OracleHelper().insert(); }}/** * Mysql数据库操作 */class MysqlHelper{ /** * 插入数据 */ public void insert(){ System.out.println("Mysql数据库插入操作"); }}/** * Oracle数据库操作 */class OracleHelper{ /** * 插入数据 */ public void insert(){ System.out.println("Oracle数据库插入操作"); }}
- 使用IOC的构造器注入方式 使用IOC你能感受到面向接口编程的思想,App.java代码如下:
package net.oseye;import org.springframework.beans.factory.BeanFactory;import org.springframework.context.support.ClassPathXmlApplicationContext;public class App { public static void main( String[] args ) { //IOC容器装载Bean定义资源 BeanFactory beanFactory=new ClassPathXmlApplicationContext("applicationcontext.xml"); //依赖装配 IDbHelperManager idbHelperManager= beanFactory.getBean("dbhelpermanager",IDbHelperManager.class); idbHelperManager.insert(); }}/** * 数据库操作管理接口 */interface IDbHelperManager{ public void insert();}/** * 数据库操作管理实现 */class DbHelperManager implements IDbHelperManager{ //构造器注入准备工作 private IDbHelper dbHelper; public DbHelperManager(IDbHelper dbHelper){ this.dbHelper=dbHelper; } public void insert(){ this.dbHelper.insert(); }}/** * 数据库操作接口 */interface IDbHelper{ public void insert();}/** * Mysql数据库操作实现 */class MysqlHelper implements IDbHelper{ public void insert(){ System.out.println("Mysql数据库插入操作"); }}/** * Oracle数据库操作实现 */class OracleHelper implements IDbHelper{ public void insert(){ System.out.println("Oracle数据库插入操作"); }}
4.0.0 net.oseye IOCDemo 1.0-SNAPSHOT jar IOCDemo http://maven.apache.org UTF-8 junit junit 4.11 test org.springframework spring-context 4.0.3.RELEASE
依赖注入三种方式
- 构造器注入 如上面Demo不在累述,构造器注入参数有值类型和引用类型(以下雷同)
- setter方法注入 通过 JavaBean的属性分配依赖性,只需要修改DbHelperManager类和配置文件即可。
class DbHelperManager implements IDbHelperManager{ //构造器注入准备工作 private IDbHelper dbHelper; public void setDbHelper(IDbHelper dbHelper){ this.dbHelper=dbHelper; } public void insert(){ this.dbHelper.insert(); }}
- 接口注入 这种方式不常用,而且具有侵入性,暂不研究!
三种注入方式都是将对象交与IOC容器管理,避免在程序中出现具体实现。通过代码我们可以看出IOC依赖注入的好处:
- 对象之间的依赖关系,不由对象自身来负责,而是由容器依据配置文件动态建立,这样就很灵活,可配;
- 采用依赖注入,模块之间一定是松散耦合的;
- 代码易维护易测试;