Spring的IOC和DI

IoC:Inverse of Control(控制反转):
读作“反转控制”,更好理解,不是什么技术,而是一种设计思想,好比于MVC。就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
正控:若调用者需要使用某个对象,其自身就得负责该对象的创建。就是new对象
反控:调用者只管负责从Spring容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架。
DI:Dependency Injection(依赖注入)
从字面上分析:
IoC:指将对象的创建权,反转给了Spring容器;
DI :指Spring创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设值给该对象。
IoC和DI其实是同一个概念的不同角度描述,DI相对IoC而言,明确描述了“被注入对象依赖IoC容器配置依赖对象”。

Container:容器,在生活中容器就是一种盛放东西的器皿,从程序设计角度看作是装对象的对象,因为存在对对象的存入、取出等操作,所以容器还要管理对象的生命周期。

在这里插入图片描述

IoC(控制反转)的概述

Spring号称是一个可以实现模块可插拔的JavaEE开发框架。那么它是如何实现程序的可插拔的呢?

实现程序可以插拔的核心理念就是,控制反转(Inversion of Control,英文缩写为IoC)

所谓的控制反转,就是将代码的调用权从调用方转移给被调用方(服务提供方)。

如图所示:

  1. 强耦合调用方式
    将A调用B的对象修改为C类的对象,修改的是调用方的代码,所以我们认为代码的调用权在调用方。

在这里插入图片描述

  1. 基于IoC(控制反转)的调用方式

将上图的需求,修改为使用Ioc的调用代码方式。就是将代码的控制权从调用方修改为被调用方,意味着,代码的调用权转移给被调用方(我们也称为服务方),不用修改调用方的的代码
只要修改配置文件就实现对象的切换。

如下图:将A类调用B类的对象修改为C类的对象,修改的是被调用方的配置文件的代码,所以代码的调用权转移到了被调用方。通过控制反转,我们可以实现增加模块或者移除模块统一由配置文件关联,增加或者移除模块,配置XML配置文件即可。

我们将代码的调用权(控制权)从调用方转移给被调用方(服务提供方)的设计模式称为控制反转(IoC)

在这里插入图片描述

根据上图可以的得出,实现一个IoC的框架,必须要解决两个问题:
1.被调用方(服务方),在程序启动时就要创建好对象,放在一个容器里面。
2.调用方使用一个接口或类的引用(不用使用new),就可以创建获得对象。

我们将这种不用new,而是根据接口或者类的引用就可以从被调用的容器里获得创建的对象的方式称为依赖注入(DI)。

所以,控制反转(Ioc),就是依赖注入加上面向接口的编程思想的实现。

在这里,我们首先抓住一个重点:Spring之所以可以实现可插拔程序,是实现了不用new,使用类或接口的引用 就可以获得获得对象!

项目目录结构

在这里插入图片描述

示例代码

CustomService接口代码

package com.spring.service;

public interface CustomService {
	
	void hello();

}

CustomServiceImpl1子类

package com.spring.service.impl;

import com.spring.service.CustomService;

public class CustomServiceImpl1 implements CustomService{

	@Override
	public void hello() {
		System.out.println("我是实现类----1");
	}

}

CustomServiceImpl2子类

package com.spring.service.impl;

import com.spring.service.CustomService;

public class CustomServiceImpl2 implements CustomService{

	@Override
	public void hello() {
		System.out.println("我是实现类--2222");
	}

}

CustomController类(调用方)

package com.spring.controller;

import com.spring.service.CustomService;

public class CustomController {

	//成员变量、字段
	private CustomService customService;

	public void setCustomServicexxx(CustomService customService) {
		this.customService = customService;
	}

	public void hello() {
		customService.hello();
	}
}

配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- 
        	让Spring框架管理对象/类
        	bean:spring管理对象的标签
        		id:唯一标识,以供其他地方调用时的引用
        		class:被管理的类的全限定名。表示需要spring创建哪个类的对象.
         -->
        
        <!-- IOC:控制反转,对象的创建交给spring -->
        <bean id="customerController" class="com.spring.controller.CustomController">
        	<!-- DI:依赖注入,对象的【属性】的值的注入
        		属性是由get、set方法来确定的。属性名是去掉get/set前缀,剩余部分的首字母小写。	
        		<property name="" value="" ref=""/>
        		name:需要注入的属性名称
        		value:值类型注入(String,各种数据类型)
        		ref:引用类型注入(如:xxxService,xxxController)
        	 -->
        	<property name="customServicexxx" ref="customerServiceImp2"/>
        </bean>

		<bean id="customerServiceImp1" class="com.spring.service.impl.CustomServiceImpl1"/>        
		<bean id="customerServiceImp2" class="com.spring.service.impl.CustomServiceImpl2 "/>        
</beans>

测试代码

package com.spring.test;

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

import com.spring.controller.CustomController;

public class SpringTest {
	
	@Test
	public void testName() throws Exception {
		//传统方式
//		CustomService customService = new CustomService();
//		customService.say();
		
		//控制反转
		//1.读取Spring配置文件,启动Spring框架,创建Spring容器对象
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		//2.从Spring容器中对象获取CustomService
		//getBean(“<bean>标签 id 值”,返回值类型);如果没有第二个参数,默认是 Object
		CustomController controller = applicationContext.getBean("customerController",CustomController.class);
		
		controller.hello();
		
	}

}

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页