Spring框架中IoC的解读

Spring框架是现在非常流行的框架之一,其两大核心技术IoC(依赖注入/控制反转)和AOP(面向切面编程),使得应用程序的组件更加快捷简易。本文用实例先对IoC的做详细介绍,希望对初学者有一定的帮助,本人能力有限,对于文章中的错误欢迎各位同道中人指正。
IoC使用两大关键技术(JDOM、反射机制)和一个设计模式(工厂模式)来实现将组建对象的控制权从代码本身转移到外部容器,以降低代码之间的耦合度。下面用代码实例的形式来说明IoC原理。
1.dao层(一个接口)

package cn.dao;

public interface DaoInte{
    public void daoMethod();
}

2.dao实现层(两个类)

package cn.dao.impl;
import cn.dao.DaoInter;

public class DaoClass1 implements DaoInter{
    @Override
    public void daoMethod() {
        System.out.println("假设这是这个类用来查询数据库的student表");
    }
}
package cn.dao.impl;
import cn.dao.DaoInter;

public class DaoClass2 implements DaoInter{
    @Override
    public void daoMethod() {
        System.out.println("假设这是这个类用来查询数据库的student表,此表经过大量的更新,包括表结构和数据");
    }
}

3.service层(一个接口)

package cn.service;

public interface ServiceInte {
    public void method1();
}

4.service实现层(一个类)

package cn.service.impl;
import cn.dao.DaoInte;
import cn.service.ServiceInte;

public class ServiceClass implements ServiceInte{
    private DaoInte dao;    //两种方法调用dao层的daoMethod
    //---------不使用IoC-----------
    public void method1(){
        dao=new DaoClass1;   //创建dao实现层DaoClass1对象,当需求更改后要创建DaoClass2对象,这是就需要更改这里的代码
        dao.daoMethod();   //调用方法
    }   

    //---------使用IoC------------
    private DaoInte getDao() {
        return dao;
    }
    public void setDao(DaoInte dao) {
        this.dao = dao;
    }
    public void method1(){
        dao.daoMethod();
    }
}

5.Spring配置文件(使用IoC时)

<beans>
    <bean id="daoBean" class="cn.dao.impl.DaoClass1"></bean>      
<!-- class值为类相对于配置文件的路径,当需要更改dao实现类时,只需要更改这里即可,即将class值改为DaoClass2,而不需要更改代码 -->
    <bean id="testService" class="cn.service.impl.ServiceClass">
        <property name="dao">   
        <!-- 给service实现层中的dao属性赋值 ,实际上是在调用里面的set方法,此处使用到*反射机制*-->
            <ref bean="daoBean"/>
        </property>
    </bean>
</beans>

可以看到,不使用Spring IoC时,调用service层,必须先new对象,将service层的接口指向具体的ServiceClass对象,才能调用其中的方法,即:

ServiceInte svi=new ServiceClass();
svi.method1();

这又将产生调用类与service层的耦合,当更改service层具体实现类时,就需要更改这里的代码。而在ServiceClass对象中需要调用dao层,此时也需要先new对象,将dao层接口指向具体的DaoClass1对象或者DaoClass2对象,这样也产生了耦合关系,代码见如上第4条不使用IoC。
总结就是,测试类管理service层的类的调用,service层管理dao层的类的调用,当更改dao层或service层的实现类,就需要更改代码来实现,当更改的需求越来越多时,将会使代码混乱。此时就需要解耦合,消除他们的依赖关系,可以建立一个bean工厂,在这个工厂中生成bean实例,并将这个实例推送给具体的调用类,那么我在这个工厂中生成什么样的bean,要调用的类就使用什么样的bean,更改时只需要更改这个工厂要生成的bean的具体实现就可以了,spring利用配置文件来完成这个工厂的创建,这就是工厂模式,代码如上第四条使用IoC和第五条配置文件的创建。到目前只是解决了service层与dao层的耦合关系,并没有解决调用service层时产生的耦合关系,实际上我们在Spring配置文件中第二个bean已经产生了具体的ServiceClass对象,其id为设置的”testService”,所以调用使就不再需要如上new对象,而是可以使用这里的ServiceClass对象,使用方法如下:

//加载配置文件(相对路径)  
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); 
//加载配置文件(绝对文件)
//new FileSystemXmlApplicationContext("..");  
ServiceClass sc=(ServiceClass)ctx.getBean("testService");
sc.method1();

这样就解决了调用service层时的耦合问题,当service层变更时只需要更改配置文件里的路径指向,而不需要更改代码。下面用一张图简单解释这种关系:
不使用IoC与使用IoC的区别
因此IoC被翻译为依赖注入或控制反转。通俗的说,IoC使得原本程序中需要什么样的对象就new什么样的对象变成配置文件的bean工厂给什么样的对象就使用什么样的对象,是一个由主动变被动的过程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章