怎么运用spring的IoC思想

来源:互联网 发布:查看本机的mac地址 编辑:程序博客网 时间:2024/06/07 20:33

Spring的反向控制(IoC):实现必须依赖抽象,而不是实现必须依赖实现。

我们来通过一个例子说明:通过来实现业务逻辑从哪个数据库中取数据的问题,取数据库的方式由两种,一个是ORACLE中取值,一个是MYSQL中取值

一、普通的做法是:

1)通常会编写一个从数据库中取值的类OracleDataBase.java,其中getDataFromOracleDataBase()OracleDataBase类的一个方法,具体负责从ORACLE数据库中取数据。

//OracleDataBase.java

Public class OracleDataBase{

      //Oracle数据库中获取数据

      publicList getDataFromOracleDataBase(){

             //具体获取oracle中的数据库的代码

}

}

2)业务逻辑类Business.java通过OracleDataBase.java中的方法来从ORACLE数据库中获取数据。

//Business.java

Public class Bussiness{

      privateOracleDataBase db= new OracleDataBase();

      //oracle数据库中获取数据

      publicList getData(){

             //具体获取oracle中的数据库的代码

             db.getDataFromOracleDataBase();

}

}

可以看出以上变成的不足之处:Bussiness类依赖于OracleDataBase类,如果业务。改变,用户现在要求从MYSQL中取数据,此时Bussiness类就适用了,必须要修改这个类。

修改方式如下,同样首先要写一个通过MYSQL获取一个数据的类和方法

//MysqlDataBase.java

Public class MysqlDataBase {

      //Mysql数据库中获取数据

      publicList getDataFromMysqlDataBase(){

             //具体获取mysql中的数据库的代码

}

}

然后通过改变Bussiness

//修改后的Business.java

Public class Bussiness{

      privateMysqlDataBase db= new MysqlDataBase ();

      publicList getData(){

             //具体获取oracle中的数据库的代码

             db.getDataFromMysqlDataBase();

}

}

那么如何来弥补这个不足,有没有一种方式可以不改变Business.java类页可以调用不同的数据库呢?

答案是可以的,这就引用到了IoC反向控制思想,通过面向抽象编程来改变这种状况。下面就用一个例子说明,编写思路是:首先编写一个获取数据的接口然后每个具体负责从各种数据库中获取数据的类都实现这个接口,而业务逻辑类中,则根据接口编程,并不与实际的类编写。

二、运营IoC编程思想

(1)    编写一个获取数据的接口DataBase.java

// DataBase.java

Public interfaceDataBase{

      //获取数据

      Public void getData();

}

(2)编写一个从Oracle数据库中获取数据的OracleDataBase.java类,该类实现DataBase.java

//OracleDataBase.java

Public class OracleDataBase implements DataBase{

      //Oracle数据库中获取数据

      publicList getDataBase(){

             //具体获取oracle中的数据库的代码

}

}

3)同样编写一个Business.java类,该类只针对接口DataBase编码,而不针对实现类。

Public class Bussiness{

 private DataBase db;

public void setDataBase(DataBasedb){

  this.db = db;

}

  public List getData(){

        //根据注入的类,从**数据库中获取数据

        db. getData();

}

}

4)编写一个测试类TestBussiness

Public class TestBussiness{

      PrivateBusiness business = new Business();

      //根据注入的数据库类,从oracle中获取数据

public void getDtata(){

      business.setDataBase(newOracleDataBase());

   business.getData();

}

}

通过这种方式就Business类就可以重用了,不管从哪个数据库中获取数据,Business类都不用改动,只要实现具体的Database接口就可以了。继续用Mysql举例

5)调用Mysql数据库取值的类,MysqlDataBase.

Public class MysqlDataBase implementsDataBase{

      //Mysql数据库中获取数据

      publicList getDataBase(){

             //具体获取Mysql中的数据库的代码

}

}

此时编写一个测试类TestBussiness

Public class TestBussiness{

      PrivateBusiness business = new Business();

      //根据注入的数据库类,从oracle中获取数据

public void getDtata(){

      business.setDataBase(newMysqlDataBase ());

   business.getData();

}

}

业务类不需要做任何修改,只需要修改测试类即可。从上面的例子可以看到,使用第一个例子,Business类依赖于具体获取数据的类;而第二个例子中,通过接口实现编程,即控制关系的反向转移,实现了IoC功能,并使代码获得了重用。这也就是实现了上面所说的“实现必须依赖抽象,而不是抽象依赖实现”。

 上面的第二种例子其实就是Spring中的Set注入。

那么有人就会问了,既然由Set注入,是不是由其它的注入方式呢?是的,接下来 就讲讲Spring的三种实现方式,用控制反转可能不太好理解,这里我们把IoC叫做依赖注入。

(PS:依赖注入是从应用程序的角度在描述,即应用程序依赖容器创建并注入它所需要的外部资源而控制反转是从容器的角度在描述,即容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。

依赖注入的另外两种形式:

1、接口注入(interface injection):就是在接口中定义要注入的信息并通过接口完成注入。

结合前面的例子我们来看看实现步骤:

(1)编写一个接口IBusiness,各种数据库的注入将通过这个接口进行。IBusiness.java代码如下:

public interface IBussiness{

       public void createDI(DataBasse db);

}

(2)任何想要使用数据库实例的类都必须使用这个接口,业务逻辑类Bussiness实现这个接口IBussiness。Business.java示例如下:

public class Bussiness implement IBussiness{

    private Database db;

    public void createDI(Database db){

        this.db=db;

    }

}

//根据注入的数据库,从**数据库中获取数据

public void getData(){

    db.getData();

}

(3)编写一个测试类Test。Test.java代码如下:

public class Test{

    private Business bussiness = new Bussiness();

    //根据注入的数据库类,从Oracle数据库中获取数据

   public void getData(){

       bussiness.createDI(new OracleDataBase);

       bussiness.getData();

    }   

}

2、构造注入(constructor injection):指在接受注入的类中定义一个构造方法,并在参数中定义需要注入的元素。为了让类Business接受Database的注入,需要为它定义一个构造方法,来接受Database的注入。Business.java的示例代码如下:

public class Bussiness{

    private DataBase db;

   public Business (DataBase db){

       this.db = db;

   }

   //根据注入的数据库类,从**数据库中获取数据

   public void getData(){

       db.getData();

  }

}

Spring支持Set注入(setter injection)和构造注入(constructor injection)。

       使用构造器注入可以在构建对象的同时一并完成依赖关系的建立,对象一建立则所有的一切也就做好准备了,但如果要建立的关系很多,使用构造器注入会在构造器方法上留下一串参数,不便于记忆,这时用Set注入是个不错的选择。使用Set可以一明确方法名称,像setXXX()这个名称比Constructor上某个参数位置代表某个对象更好。

       但是使用Set注入由于提供了SetXXX()方法,所以不能保证相关的数据成员或资源在执行时不会被更改设定,so,如果开发人员想要让一些数据成员或资源变为只读或是私有,构造器会更简单。