Spring IOC&DI 控制反转和依赖注入
控制反转(Inversion of Control,缩写为IOC),它是把你设计好的对象交给spring控制,而不再需要你去手动 new Object(); 网上对于IOC的解释很多,对程序员而言,大篇文字的解释,不如代码举个例子:
汽车(Car )、汽车车身 (CarBody) 、 汽车轮子(CarWheel )
汽车 由 id + name + 车身 + 轮子 组成
代码如下:
package com.wp; public class Car { private int id; private String name; private CarBody carbody; private CarWheel carwheel; // get set 方法省略。。。 }
package com.wp; public class CarBody { private int id; private String name; //get set 方法省略。。。 }
package com.wp; public class CarWheel { private int id; private String name; //get set 方法省略。。。 }
以往的方式:我们创建汽车对象是通过直接new Car(); 的方式去出动创建对象,也就是对象的创建是有我们程序去主动控制的。代码如下:
package com.wp.test; import com.wp.Car; public class TestSpring { public static void main(String[] args) { Car car = new Car(); System.out.println(car); //输出 com.wp.Car@452b3a41 } }
在Spring中,也可以让spring自动创建对象,代码如下:
首先在 applicationContext.xml 进行配置,配置class指向我们的Car 通过关键字c可以获取Car对象,并且会默认给Car对象的name属性赋值“小汽车”。
<bean name="c" class="com.wp.Car">
<property name="name" value="小汽车" />
</bean>
测试类使用spring自动创建对象,代码如下:
package com.wp.test; import com.wp.Car; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpring { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" }); Car car = (Car) context.getBean("c"); System.out.println(car.getName()); //输出 小汽车 } }
这种方式就是spring自动创建对象的方式,我们需要Car对象的时候,我们直接找Spring的IOC容器要就行了,我们不需要知道这个对象怎么创建的,我们需要就直接取。
通过上面的例子来解释一下 控制反转:
以往的时候,Car对象是我们程序创建,需要手动 new Car() 来创建Car对象,Car的创建是由我们控制的;
使用Spring 的IOC原理之后,Car对象由Spring 创建,我们需要的时候,直接去取,Car的创建由Spring 控制。
对象的创建由我们控制转变为Spring控制,这种设计思想,就叫控制反转。
依赖注入:
什么是依赖注入呢?简单点,程序员还是通过程序的方式来理解。
可以看到我们的 CarBody 和 CarWheel 还没派上用场,也就是我们在上面创建的小汽车的车身和轮子还都是空的,这个小汽车是无法使用的,为了让小汽车变的完整,我们要给小汽车创建车身和轮子组装上。还是通过以往的形式和依赖注入的形式来对比:
以往的方式:
我们会 new CarBody() ,然后通过Car的setCarBody() 把这对象放进去;
然后再 new CarWheel () ,然后通过Car的setCarWheel() 把这对象放进去。
一顿操作以后,我们的小汽车就完整了,代码如下:
package com.wp.test; import com.wp.Car; import com.wp.CarBody; import com.wp.CarWheel; public class Test { public static void main(String[] args) { Car car = new Car(); //创建小汽车 CarBody carbody = new CarBody(); //创建车身 CarWheel carwheel = new CarWheel(); //创建轮子
car.setCarbody(carbody); //给小汽车装上车身 car.setCarwheel(carwheel); //给小汽车装上轮子
System.out.println(car.getCarbody()); //输出 com.wp.CarBody@452b3a41 } }
使用Spring 的依赖注入方式:
修改applicationContext.xml 配置文件,通过前门spring创建小汽车对象的方式,把小汽车的车身和车轮也交给spring创建,然后通过 ref ="cb" 和 ref = "cw"的方式把车身和轮子组装到小汽车上。注意:cb 和 cw 分别对应 车身 、轮子 bean 的name
<bean name="c" class="com.wp.Car"> <property name="name" value="小汽车" /> <property name="carbody" ref="cb" /> <property name="carwheel" ref="cw" /> </bean> <bean name="cb" class="com.wp.CarBody"> <property name="name" value="豪华车身" /> </bean> <bean name="cw" class="com.wp.CarWheel"> <property name="name" value="豪华轮子" /> </bean>
测试类如下:
package com.wp.test; import com.wp.Car; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpring { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" }); Car car = (Car) context.getBean("c"); System.out.println(car.getName()); //输出 小汽车 System.out.println(car.getCarbody().getName()); //输出 豪华车身 System.out.println(car.getCarwheel().getName()); //输出 豪华轮子 } }
我们已经能够理解汽车是Spring创建的,通过 context.getBean("c") 可以直接获取汽车对象,也就是我们不需要创建对象,我们交给Spring去创建,我们需要用的时候,只管去向Spring容器要,Spring容器就会给我们一个创建好的对象。那么Spring 是如何把“车身”和“轮子”组装到“小汽车”上面呢,这就用到了依赖注入
依赖注入(Dependency Injection)也是Spring框架的核心之一,缩写 DI ,
在applicationContext.xml 配置文件中
<bean name="c" class="com.wp.Car">
<property name="name" value="小汽车" /> <property name="carbody" ref="cb" /> <property name="carwheel" ref="cw" /> </bean>
首先看下name的赋值方式,创建Car对象时,要给 name 属性赋值,赋值方式是直接指定一个value="小汽车" 也就是创建一个Car对象,直接把小汽车这个字符串赋到Car对象的name属性上,小汽车就有名字了。
然后看下 carbody 赋值方式,赋值方式是 ref = "cb" ,spring会自动去寻找name="cb"的 bean ,而这个bean 对应的实体类就是CarBody 类 ,在找到之后,Spring会创建CarBody 对象,然后把CarBody对象赋到 Car对象的carbody 属性上面, 小汽车就有车身了。
CarWheel 原理与CarBody一样。
Car 需要CarBody ,也就是Car 依赖CarBody ,Spring这种把 CarBody对象 注入到 Car 对象中的方式,就是依赖注入(DI)。
那么spring是如何实现依赖注入呢?
那就是反射(reflection) , <property name="carbody" ref="cb" /> 中的ref 就是反射的缩写,这个由spring自动完成,我们不需要去进行任何操作。
使用IOC 和 DI 有什么好处?
以往的方式我们类里面主动创建对象,然后处理对象与对象的依赖,会导致类与类之间高耦合,使用IOC和DI 之后呢,我们把类的控制权交给Spring,Spring去进行创建对象并且进去对象依赖注入,我们只是在需要的时候去找Spring的IOC容器去取,可以让我们的系统结构更加灵活。
另外:
如果感觉配置文件写的不方便,也可以写成注解的方式:
applicationContext.xml
<context:annotation-config/>
Car 的属性上增加@Autowired注解
package com.wp; import org.springframework.beans.factory.annotation.Autowired; public class Car { private int id; private String name; @Autowired private CarBody carbody; @Autowired private CarWheel carwheel;
//get set 方法省略。。。 }
注解运行结果与配置文件运行结果一致。
加油!