概念
控制翻转, 也叫依赖注入, 他不会直接创建对象, 只是把对象声明出来, 在代码中不直接与对象和服务进行连接, 但是在配置文件中描述了哪一项组件需要哪一项服务, 容器将他们组件起来. 在一般的IOC场景中容器创建了所有的对象, 并设置了必要的属性将他们联系在一起, 等到需要使用的时候才把他们声明出来, 使用注解就更方便了,容器会自动根据注解把对象组合起来.
我认为的控制反转就是: 将对组件对象控制权的转移, 从程序代码本身转移到了外部容器.
作用
1.管理对象的创建和依赖关系的维护. 对象的创建并不是一件简单的事, 在对象关系比较复杂时, 如果依赖关系需要程序员来维护的话,那是相当头疼的.
2.解耦, 由容器去维护具体的对象
3.托管了类的产生过程, 比如我们在需要在类的产生过程中做一些处理, 最直接的例子就是代理, 如果有容器程序可以把这部分处理交给容器, 应用程序则无需去关心类是如何完成代理的.
优点
1.IOC或依赖注入把应用的代码量降到最低
2.他使应用容易测试,,单元测试不再需要单例和JNDI查找机制
3.最小的代价和最小的侵入性使松散耦合得以实现
4.IOC容器支持加载服务时的饿汉式初始化和懒加载
实现机制
实现原理是工厂模式+反射机制
实例代码
组装一台打印机
打印机:
public class Printer {
private Ink ink;
private Paper paper;
public void setInk(Ink ink) {
this.ink = ink;
}
public void setPaper(Paper paper) {
this.paper = paper;
}
public void print(String msg){
ink.showInf();
paper.showSize();
System.out.println(msg);
}
}
墨盒(黑白墨盒,彩色墨盒)
public interface Ink {
void showInf();
}
public class BlackInk implements Ink {
public void showInf() {
System.out.println("黑白墨盒");
}
}
public class ColorInk implements Ink {
public void showInf() {
System.out.println("彩色墨盒");
}
}
纸张(A4,A5)
public interface Paper {
void showSize();
}
public class A4 implements Paper {
public void showSize() {
System.out.println("A4");
}
}
public class A5 implements Paper {
public void showSize() {
System.out.println("A5");
}
}
在配置文件中组装打印:
<!-- 注册基本组件 -->
<bean id="blackInk" class="com.st.spring.demo1.BlackInk"/>
<bean id="colorInk" class="com.st.spring.demo1.ColorInk"/>
<bean id="a4" class="com.st.spring.demo1.A4"/>
<bean id="a5" class="com.st.spring.demo1.A5"/>
<!-- 有彩色墨盒和A5纸张的打印机 -->
<bean id="print1" class="com.st.spring.demo1.Printer">
<property name="ink" ref="colorInk"/>
<property name="paper" ref="a5"/>
</bean>
<!-- 黑白墨盒A4纸张 -->
<bean id="print2" class="com.st.spring.demo1.Printer">
<property name="paper" ref="a4"/>
<property name="ink" ref="blackInk"/>
</bean>
测试:
@Test
public void testSpring(){
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
//取出打印机对象
Printer p1 = (Printer)ac.getBean("print1");
p1.print("print1");
Printer p2 = (Printer)ac.getBean("print2");
p2.print("print2");
}