Spring IOC 反转控制

Spring IOC

     IOC(Inversion of Control),译作反转控制,其功能是将类之间的依赖转移到外部的配置文件中, 避免在调用类中硬编码实现类,因此也被称作依赖注入(Dependency Injection)。在以往的开发中, 通常利用工厂模式(Factory)来解决此类问题,其实不管是工厂模式还是依赖注入,调用类与实现类不可 能没有任何依赖,工厂模式中工厂类通常根据参数来判断该实例化哪个实现类,Spring IOC将需要实例的 类在配置文件文件中配置。使用Spring IOC能得到工厂模式同样的效果,而且编码更加简洁。看段代码比较 一下:

一、用工厂模式来实现

例 1.1. Product.java

public interface Product 

{

public void execute();

}


例 1.2. ConcreteProductA.java

public class ConcreteProductA implements  Product

{

public void execute()

{

...

}

}


例 1.3. ConcreteProductB.java

public class ConcreteProductB implements  Product

{

public void execute()

{

...

}

}


例1.4. Factory.java

public class Factory

{



public Product CreateProduct(object param)

{

return ConstructObjects(param);

}



private Product ConstructObjects(object param)

{

...

}

}


例 1.5. Client.java(调用类)

public class Client

{

public Client()

{

//实例化ConcreteProductA

Product product = Factory.CreateProduct(paramA);



//实例化ConcreteProductB

Product product = Factory.CreateProduct(paramB);

...

}

}


在ConstructObjects方法中设定实例化实现类的逻辑,这样对于调用类来说,不直接实例化实现类,纵然实现类发生变化, 调用代码仍然可以不作修改,给维护与扩展带来便利。

二、Spring IOC实现

例 1.6. SpringConfig.xml

<bean id="productA" class="ConcreteProductA" />

<bean id="productB" class="ConcreteProductB" />




例 1.7. Client.java(调用类)

public class Client

{

public Client()

{

//实例化ConcreteProductA

Product product = (Product)InitSpring.getObject("productA");



//实例化ConcreteProductB

Product product = (Product)InitSpring.getObject("productB");

...

}

}


调用代码中没有硬编码实现类,比较工厂模式,少了Factory类。

Spring为依赖注入提供三种实现方式:接口注入、设值注入、构造注入。利用这些可以灵活的解决 类之间的依赖关系,让你为所欲为的组装代码。与其说Spring IOC是一个工具,还不如说搭建了一 个思想的舞台。继续看代码:

来实现一个操作多个数据源的切换

例 1.8. DataSource.java

public class DataSource

{

private String driverClassName;

private String url;

private String username;

private String password;



public String getDriverClassName()

{

return this.driverClassName;

}



public void setDriverClassName(String driverClassName)

{

this.driverClassName = driverClassName;

}



public String getUrl()

{

return this.url;

}



public void setUrl(String url)

{

this.url = url;

}



public String getUsername()

{

return this.Username;

}



public void setUsername(String username)

{

this.username = username;

}



public String getPassword()

{

return this.password;

}



public void setPassword(String password)

{

this.password = password;

}

}


例 1.9. DataAccessor.java

public class DataAccessor

{

private DataSource dataSource;

public void setDriver(DataSource dataSource)

{

this.dataSource = dataSource;

}



public void save(String sql)

{

Statement s = getStatement();

try

{

s.getConnection().setAutoCommit(false);

int rows = s.executeUpdate(sql);

s.getConnection().commit();



}

catch(Exception e)

{

s.getConnection().rollback();

...

}

finally

{

...

}

}



private Statement getStatement()

{

Statement s;

try

{

Class.forName(dataSource.getDriverClassName()).newInstance();

java.sql.Connection conn =

java.sql.DriverManager.getConnection(dataSource.getUrl(),dataSource.getUser(),dataSource.getPassword());

try

{

s = c.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

}

}

catch(Exception e)

{

...

}

return s;

}

}


例 1.10. BussinessA.java

public class BussinessA

{

private DataAccessor dao;

public void setDao(DataAccessor dao)

{

this.dao = dao;

}



public void execute()

{

dao.save("insert into tb1 ...");

}

}


例 1.11 BussinessB.java

public class BussinessB

{

private DataAccessor dao;

public void setDao(DataAccessor dao)

{

this.dao = dao;

}



public void execute()

{

dao.save("insert into tb2 ...");

}



}


全部代码就这样了,执行BussinessA.java、BussinessB.java代码即可完成数据插入操作,从代码中看, 这两个类具体操作的是什么数据库?什么样的操作细节?让你失望了,代码中找不到这样的关联,看配置文件吧:

例 1.12. SpringConfig.xml

<bean id="dataSourceA" class="DataSource" destroy-method="close">

<property name="driverClassName"><value>org.gjt.mm.mysql.Driver</value></property>

<property name="url">

<value>jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=GBK</value>

</property>

<property name="username"><value>root</value></property>

<property name="password"><value></value></property>

</bean>



<bean id="dataSourceB" class="DataSource" destroy-method="close">

<property name="driverClassName"><value>org.gjt.mm.mysql.Driver</value></property>

<property name="url">

<value>jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=GBK</value>

</property>

<property name="username"><value>root</value></property>

<property name="password"><value></value></property>

</bean>



<bean id="daoA" class="DataAccessor">

<property name="dataSource">

<ref local="dataSourceA"/>

</property>

</bean>



<bean id="daoB" class="DataAccessor">

<property name="dataSource">

<ref local="dataSourceB"/>

</property>

</bean>



<bean id="bussinessA" class="BussinessA">

<property name="dao">

<ref local="daoA"/>

</property>

</bean>



<bean id="bussinessB" class="BussinessB">

<property name="dao">

<ref local="daoB"/>

</property>

</bean>




看完配置文件应该明白了,这里承担了所有的依赖关系。

  • 首先,我们通过设值注入方法设置数据源相关参数

  • 然后,我们将数据源实例注入给数据访问类

  • 最后,我们为每个具体业务类注入相应访问器

是不是感觉想玩积木似的,在组装你的代码?

例 1.13. DaoTest.java

public void testSave()

{

BussinessA bussinessA = (BussinessA)InitSpring.getObject("bussinessA");

bussinessA.execute();



bussinessB bussinessB = (BussinessB)InitSpring.getObject("bussinessB");

bussinessB.execute();

}


执行这段测试代码,数据库Test1、Test2中tb1、tb2表将分别插入对应的数据,从实现代码来看操作多个数据库和 操作一个数据库完全一样,即使当数据源,数据访问类不断变化,应用代码也可以做到不用任何修改。

希望看完本章节的内容能让读者与我共鸣,Spring IOC是一种优雅的思想,借助它发挥你无穷的想象吧。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值