一、什么是IOC?
1、在实际的开发过程中,编程中难免会对象之间的依赖关系,所谓的依赖关系可以简单这样理解(纯属瞎编的):
- 人类是需要生存的:Person类
- 所以人类是需要吃饭的:Eat类
- 吃饭则需要食物:Foods类
也就是Person生存需要依赖Eat,Eat则需要Foods。
但是在开发过程中,对象之间的依赖关系会比这更加复杂,则会出现“牵一发而动全身”的问题,导致对象之间的依赖关系很紧密,耦合程度很高。一般的业务之间,业务与持久层等之间都存在这样的问题,那么如何让降低对象之间的依赖关系呢,IOC正是为这个解决这个问题而出现的。
2、传统的实现中,是由程序内部的代码来控制对象之间的关系,就是new来创建它的依赖对象,实现两个组件间的组合关系。而IOC控制反转是指应用程序中对象的创建、销毁等不再由程序本身来完成,而是由外部的Sprimg容器在程序运行时来注入到程序中。
对象的生命周期不再受程序本身决定,而是由Spring容器控制,这样就很好地降低了对象之间的耦合度。
3、IOC是一种设计思想,不是一种技术。这种思想就是“Don’t call us, we’ll call you (不要打电话给我们,我们需要时会打电话通知你的)”,就是好莱坞设计原则(告诉开发者不要主动去构造依赖,而是需要时由容器将对象注入进来)
二、通过实例理解IOC
不通的动物会有不同的运动方式, 有的是跑run,有的是飞fly,下面通过具体变成加深对IOC的理解。程序文件的结构图如下所示。
1、创建抽象接口Moveable。
package com.ioc;
//Moveable.java:抽象接口Moveable,符合依赖倒置原则
public interface Moveable {
void move();
}
2、创建Animal类:
package com.ioc;
//Animal.java:
public class Animal implements Moveable {
private String animalType;//何种动物
private String moveMode;//是如何运动的
public void setAnimalType(String animalType) {
this.animalType = animalType;
}
public void setMoveMode(String moveMode) {
this.moveMode = moveMode;
}
public void move() {
String moveMessage = animalType+" can "+moveMode;
System.out.println(moveMessage);
}
}
3、添加Spring配置信息
建立Spring的配置文件bean.xml,放在src文件夹中,即在CLASSPATH路径下。
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
<!--对象可以通过id值animal来获取 -->
<bean id="animal" class="com.ioc.Animal">
<!--设置animalType属性值为Bird -->
<property name="animalType">
<value>Bird</value>
</property>
<!--设置moveMode属性值为fly -->
<property name="moveMode">
<value>fly</value>
</property>
</bean>
</beans>
该配置文件的作用是:将ioc.Animal类实例化对象,该对象Animal可以通过id值获取,并可以property设置对象的animalType值为Bird,设置moveMode属性值为fly。
4、创建测试类Test
package com.ioc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
//创建Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
//从容器中获取Animal类的JavaBean实例
Moveable animal = (Moveable)ctx.getBean("animal");
//调用move方法
animal.move();
}
}
Test.java的作用:首先是加载Spring容器,然后通过键值animal在容器中后去Animal的类JavaBean实例。同时将animalType和moveMode的属性值注入该对象,最后调用对象的move方法。
最后的结果显示:Bird can fly
三、Spring IOC总结
总结上述IOC,可以总结为以为内容:
Spring IOC最终目的就是降低项目中对象之间的耦合度,使系统更加稳定。
Spring IOC是负责控制对象的生命周期和对象间的关系,可以举这样一个例子:我们要去聚餐,需要汇总大家想吃的食物,A想吃辣的,B想吃甜的等等各种各样的需求(需求各种各样的实体类),那么我们要去餐馆订好菜单,这里的餐馆就相当于一个Spring容器,所以我们想吃的各色各类的饭菜都在里面,预定的时候我们想吃什么菜,餐馆就会把相应的饭菜在我们人来齐的时候上桌(Spring容器在系统运行到合适的时候,把你想要的实例主动注入给你),而我们并不需要知道饭菜是怎么做的以及什么时候完成的(Spring容器完全控制,不必知道),我们也没必要去自己做菜(自己new object()创建对象)而饭菜的产生(类的创建)、处理吃剩的饭菜(类的销毁)都是由餐馆(Spring容器)负责的。
IOC的一个重点就是在系统运行的时候,动态地向对象注入它所需要的对象,这是通过DI(Dependency Injetion)依赖注入实现的。