Spring_IoC控制反转、依赖注入详解

Spring_IoC

一、IoC相关概念简介
1、理解【控制】和【依赖】的概念

IoC即控制反转、依赖注入 。—— OOAD依赖倒置

【控制】和【依赖】都代表对象之间的关联关系,而且他们在Spring中是一对近义词,控制和依赖几乎是并存的。

例如,现有如下需求:汽车的功能是行驶,司机的功能是驾驶汽车,令汽车行驶。

我们可以通过代码描述上述关系:

public class Car {
   	// 汽车类
    private String name;	// 品牌
    private Double price; 	// 价格

	public void run(){
   	// 汽车行驶方法
		System.out.println("Car : I'm running!");
	}
}
public class Driver {
   	// 司机类
	public Car car;
	public void drive() {
    // 司机驾驶方法
		car.run();
	}
}

上述案例中,司机可以调用驾驶方法,令其包含的汽车对象执行行驶方法。需要关注的问题是,car对象是如何被实例化的。

在传统的Java编程中,我们习惯于将这个car对象通过new的方式创建出来。那么什么时候去new它呢?答案是不唯一的。例如:

1)声明的同时实例化
public class Driver {
   
    Car car = new Car()public void drive(){
   	
        car.run();
    }
}
2)在调用时进行实例化
public class Driver {
   
    Car car;
    public void drive(){
   
        car = new Car();
        car.run();
    }
}

上述两种方式,Car对象被创建的时机不同。但是相同的是,new Car()的过程都发生在Driver类中。这样的形式,我们称之为Driver在自己的【代码内部】,控制了一个Car。

注意,这里的【控制】强调的是控制Car对象的创建,而并非Car对象方法的调用。

而【依赖】是指,此时Driver的正常工作需要依赖于Car。换言之,Driver和Car产生了耦合。

耦合是指对象之间相互依赖的程度。在软件设计和开发中,我们要尽可能地降低类之间的耦合度。一个类如果出现了异常,或发生了改变,那么依赖于它的其他所有类可能都不能正常运行,导致程序大面积的瘫痪,也称为雪崩效应。

2、IoC 控制反转

IoC即Inversion of Control,控制反转。

可以理解为“反转”对象的控制关系,或“改变”对象的控制关系。

传统的Java SE编程中,对象之间的关系是在【对象内部】直接控制,而IoC正是改变了这样的控制关系,改为由【外部容器】来控制。

大致的过程是,我们不再像原来那样将new操作写死在类中,而是将对象之间的关联关系定义在一个xml配置文件中。在程序运行期间,再由容器根据配置文件中定义的规则管理对象的生命周期,并建立对象之间的关联关系。

也可以这样理解,传统的写法是在编译期间就将对象关系规定死,程序运行时一定会按照这样的规则去执行。而Spring IoC的做法是在编译期间将对象全部分离,当进入到运行阶段再将他们动态结合到一起。

IoC体现了好莱坞原则,即“不要打电话过来,我们会打给你”。

3、依赖注入和依赖查找
public class Student{
	private int id;
	private String name;
	private Teacher teacher;
}

	Student stu = new Student();
	Teacher teacher = new Teacher();
	stu.setTeacher(teacher);

理解两个名词:

1)DI(Dependency Injection) 依赖注入 (要求掌握,核心内容)

​ 依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。

2)DL(Dependency Loopup) 依赖查找 (了解即可)

​ 容器创建对象并提供回调接口和上下文环境给组件,需要时通过接口从容器中查找对象(理解即可)

DI和DL的关系:

​ 假设现在需要使用A对象,A对象中需要配置一个B对象。那么我们在容器中配置一个A对象,配置一个B对象,并声明B对象是A对象的一个属性。这个过程叫做依赖注入。

​ 如果你想从容器中取出某个对象对其进行操作,可以调用context组件的相关方法,根据特定的方式获取容器中的Bean。这个过程叫做依赖查找。

DI、DL和IoC的关系:

​ IoC是一种思想,而DI和DL是实现这种思想具体的方式。

​ 从实际角度出发分析,IoC解决了对象由谁来创建、对象之间存在什么何种关联关系的问题

​ 而DI解决了对象之间的关联关系如何建立的问题

IoC和DI总结:

​ 简而言之,原本我们在代码中会频繁地new对象,现在使用IoC(DI),我们会观察到类似这样的效果:只需要在类中定义需要什么对象作属性,你也可以在方法中让这个对象去调用方法。而这样做并不会抛出空指针异常,因为IoC容器发现你需要用到这个对象时会先帮你进行注入。

二、Core、Beans、Context组件概念
1、组件及原理简介

Spring中包含诸多组件,其中Core、Beans、Context是最核心的三个组件。

它们组合起来,就实现了Spring中最核心的功能——IoC。

IoC是Spring功能的根基。如果没有IoC的存在,就不可能实现AOP、Web等其他上层功能。

通俗地来讲,三个组件的功能及角色如下:

  • Beans:组件(Bean的复数形式)

  • Context:容器(用来包含组件)

  • Core:工具

首先,Bean是Spring中最为核心的概念。Spring框架可以说就是在面向Bean编程。Bean之于Spring相当于Object之于OOP。在Spring中,所有的Java对象都是Bean。

IoC的核心概念是将Bean配置到容器中,而这个容器就是由Context来充当。在编译阶段,我们以xml文件的方式定义容器配置,声明Bean相关内容。运行期间,Spring会解析xml容器配置文件,将其中的内容封装成一个Context对象。我们可以通过这个Context对象获取到容器中的Bean。

Core是处理容器和Bean的一些工具和方法,如果把Core改称为Util就很好理解了。

如果说Context是一个舞台,那么Bean就是这个舞台上的演员。而Core就是演员演出所用的道具。

2.容器xml配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-4.2.xsd">
	
		<bean></bean>

		<bean></bean>
</beans>
三、IoC常用jar包

如果需要在项目中使用基本的IoC功能,通常需要引入如下jar文件(版本信息省略):

spring-beans.jar

spring-context.jar

spring-core.jar

spring-expression.jar

junit.jar

commons-logging.jar

四、Bean对象的定义和获取
1、在容器中声明对象

【类声明】Car.java:

public class Car {
   
    private String name;		// 车名
    private double price;	// 价格
    getters/setters...
}

【配置文件】bean.xml:

<bean id="mycar" class="com.briup.day01.Car"></bean>
2、在代码中获取容器中的对象

创建测试类BeanTest.java:

public class SetterTest {
   

    @Test
    public void bean_test() {
   
        // 创建容器对象
        ApplicationContext context = new ClassPathXmlApplicationContext(
            "com/briup/day01/bean.xml");

        // 获取Bean
        Car car = (Car) context.getBean("mycar");

        // 打印输出
        System.out.println(car);
    }
五、IoC注入方式

什么是注入?

​ 【注入】也称装配,即为对象的属性赋值。

通过注入,可以为容器中的基本属性赋值,例如学生学号、姓名、年龄等,也可以通过注入来创建对象之间的关联关系。例如,在Driver对象中注入一个Car对象,此时由Car对象充当Driver对象的属性。

IoC实现注入有三种常用方式:

  • set注入

  • 构造器注入

  • 接口注入

比较常用的是set和构造器注入,接口注入用于引入外界系统资源,例如JNDI。

1.set注入

要求:要注入的属性必须包含对应的set方法。

可以注入的类型:①基本数据类型和String类型 ②对象类型 ③集合类型

1)基本数据类型

【配置文件】bean.xml:

<bean id="mycar" class="com.briup.day01.Car">
	<property name="name" value="兰博基尼">
	<property name="price">
		 <value>10.5</value>
	</property>
</bean>

bean中的属性,id为该对象在容器中起一个名字,class指定对象类型。

除了id之外还可以使用name属性为Bean起名字。
id和name区别在于,id是唯一标识,并且要求比较严格。

容器会检查id属性值是否符合规(名字是否重复、是否以数字开头、是否包含空格等等),但是name不会检查这些内容。

<property>元素用来为属性赋值,每个<property>元素为对象的一条属性赋值。

name属性用来指定属性名,例如name="price"代表当前<property>是为了给Car对象的price属性赋值。

value属性是具体的值,也可以定义为<property>中的子元素。

2)对象类型

【配置文件】bean.xml:

<bean id="mycar" class="com.briup.day01.Car">
	<property name="name" value="兰博基尼">
	<property name="price">
		 <value>10.5</value>
	</pro
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值