Spring IOC和DI

控制反转IOC

例子:

你想吃面包,这时候有两种情况:

1 你家附近没有面包店,你就要自己买原材料自己做面包(传统编程模式:需要自己new对象)

2 你家附近有面包店,那么你只要把你想要吃的口味告诉店家,一会你就可以吃到面包了(控制反转:自己不new对象,对象由框架交给你)

注意:你没有制作面包,而是由店家制作面包,但是完全符合你的口味

控制反转:就是对象由Spring容器创建和管理,调用者只负责使用,降低耦合度,控制权由调用者转移到Spring容器,控制权产生了反转。

依赖注入:从Spring容器角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它所依赖的实例。

所以,控制反转是一种通过描述(Spring中可以是XML文件或注解)并通过第三方去产生或获取特定对象的方式。

Spring中实现控制反转的是IOC容器,其实现方式是依赖注入(DI)


 

IOC容器的设计主要是基于BeanFactory和ApplicationContext两个接口

applicationContext.xml

<bean id="test" class="dao.TestDaoImpl" />

dao/ITestDao.java(接口)

package dao;

public interface ITestDao {
    public void sayHello();
}

dao/TestDaoImpl.java(实现类)

package dao;

public class TestDaoImpl implements ITestDao{

    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("Hello,Study hard!");
    }
    
}

test/Tests.java(测试类)

package test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import dao.ITestDao;

public class Tests {
    
    @Test
    public void test1() {
        //初始化spring容器ApplicationContext,加载配置文件
        ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
        //通过容器获取test实例
        ITestDao tt = (ITestDao) appCon.getBean("test");
        tt.sayHello();
    }
}

 


 

依赖注入(DI)

依赖注入是Spring中实现IOC容器的方法,其作用是在使用spring框架创建对象时动态的将其所依赖的对象或属性值注入bean组件中

依赖注入通常使用两种方式实现:构造方法注入和setter方法注入


1.构造方法注入

applicationContext.xml内容

<!-- 将指定类DIServiceImpl配置给spring,让spring创建其实例 -->
<bean id="myTestDao" class="dao.TestDaoImpl"></bean>
<!-- 使用构造方法注入 -->
    <bean id="diService" class="service.DIServiceImpl">
    <!-- 将myTestDao注入到DIServiceImpl类的属性ITestDao上 -->
    <constructor-arg index="0" ref="myTestDao" />
</bean>

service.IDIService.java

package service;
/**
 * 使用构造方法依赖注入ITestDao接口对象
 *
 * Title: IDIService
 *
 * Description: 
 *
 * @author Ethan
 *
 * @date 2019年6月25日
 *
 */
public interface IDIService {
    public void sayHello();
}

service.DIServiceImpl.java

package service;
/**
 * IDIService接口的实现类
 *
 * Title: DIServiceImpl
 *
 * Description: 
 *
 * @author Ethan
 *
 * @date 2019年6月25日
 *
 */

import dao.ITestDao;

public class DIServiceImpl implements IDIService{
    private ITestDao iTestDao;
    //构造方法,用于实现依赖注入接口对象iTestDao
    public DIServiceImpl(ITestDao iTestDao) {
        super();
        this.iTestDao = iTestDao;
    }
    public void sayHello() {
        //调用iTestDao中的sayHello方法
        iTestDao.sayHello();
        System.out.println("IDIService构造方法注入");
    }
    
}

测试类:

test.Tests2.java

package test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import service.IDIService;

public class Tests2 {
    
    /**
     * 构造方法注入测试类
     *
     * Title: Test1
     *
     * Description: 
     * 
     *
     */
    @Test
    public void Test1() {
        ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
        IDIService ts = (IDIService) appCon.getBean("diService");
        ts.sayHello();
    }
}

运行结果:

Hello,Study hard!
IDIService构造方法注入

 


 

2 setter方法注入

在上面的结构中加入service.DIServiceImpl.java

package service;

import dao.ITestDao;

public class DIServiceImpl1 implements IDIService{
    private ITestDao iTestDao;
    //添加iTestDao的setter方法,用于实现依赖注入

    public ITestDao getiTestDao() {
        return iTestDao;
    }

    public void setiTestDao(ITestDao iTestDao) {
        this.iTestDao = iTestDao;
    }

    public void sayHello() {
        // TODO Auto-generated method stub
        //调用iTestDao中的sayHello方法
        iTestDao.sayHello();
        System.out.println("TestDaoImpl setter方法注入");
    }
    
    
}

applicationContext.xml加入

<!-- 使用setter方法的注入 -->
    <bean id="testDIService1" class="service.DIServiceImpl1">
        <!-- 调用DIServiceImpl1类的setter方法,将myTestDao注入到DIServiceImpl1类的属性iTestDao上 -->
        <property name="iTestDao" ref="myTestDao" />
    </bean>

测试类:Tests2.java中加入

/**
     * 使用setter方式注入测试类
     *
     * Title: Test2
     *
     * Description: 
     * 
     *
     */
    @Test
    public void Test2() {
        ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
        IDIService ts = (IDIService) appCon.getBean("testDIService1");
        ts.sayHello();
    }

运行结果:

Hello,Study hard!
TestDaoImpl setter方法注入

 


 

 

思考

1 IOC容器的实现方式有哪些?

2 在spring框架中什么是控制反转?什么是依赖注入?使用控制反转与依赖注入有什么优点?

3 spring框架采用java的什么机制进行依赖注入

 

posted @ 2019-06-24 20:21  WaterGe  阅读(198)  评论(0编辑  收藏  举报