IOC概述
-
SpringIOC是java后端使用的一种工厂模式思想,IOC不是一项技术,而是一个编程思想。那么,工厂模式和IOC运用是解耦,而IOC特殊之处在于控制反转。
-
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。概括:把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
-
依赖注入:把有依赖关系的类放到容器中,解析出这些类的实例。可以理解为,我们在当前对象去实例一个接口相关对象时,我们不再去new这个相关对象,而是将其封装为一个方法,只需要从外部注入便可。依赖注入是控制反转的关键。
图解:
将老板跟需要购买的产品交给管家来联系,小明只需要根据管家的指示去完成采购。
未使用IOC时采购方式
产品接口:
public interface IProduct {
public void ipad();
public void phone();
}
产品:
public class XMProduct implements IProduct{
public void ipad() {
System.out.println("小米平板");
}
public void phone() {
System.out.println("小米手机");
}
}
public class HWProduct implements IProduct{
public void ipad() {
System.out.println("华为平板");
}
public void phone() {
System.out.println("华为手机");
}
}
- 小明:
public class XiaoMing {
private XMProduct product = new XMProduct();
public void buyIpad() {
System.out.print("小明购买了");
product.ipad();
}
public void buyPhone() {
System.out.print("小明购买了");
product.phone();
}
}
此时小明需要自己去寻找需要购买的产品 ( new XMProduct();)
弊端:如果是购买其他的产品那么还需要自己去找(new 其他产品)可见当前的代码是高度耦合的。
- 采购:
public class Test {
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing();
xiaoMing.buyIpad();
xiaoMing.buyPhone();
}
}
-
UML图:
-
小明(依赖注入)
public class XiaoMing {
private IProduct product ;
public void buyIpad() {
System.out.print("小明购买了");
product.ipad();
}
public void buyPhone() {
System.out.print("小明购买了");
product.phone();
}
//依赖注入
public void setProduct(IProduct product) {
this.product = product;
}
}
- 采购(依赖注入)
public class Test {
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing();
xiaoMing.setProduct(new XMProduct());
xiaoMing.buyIpad();
xiaoMing.buyPhone();
}
}
通过依赖注入的方法小明不再自己去找产品,而是等别人告诉他。
- UML图
SpringIOC(运用管家管理)
小明:
@Component
public class XiaoMing {
@Autowired
private IProduct product ;
public void buyIpad() {
System.out.print("小明购买了");
product.ipad();
}
public void buyPhone() {
System.out.print("小明购买了");
product.phone();
}
}
采购:
@ComponentScan
public class Test {
public static void main(String[] args) {
//创建了Spring容器
ApplicationContext context = new AnnotationConfigApplicationContext(Test.class);
//获取SpringHello类型的对象,大写开头对象被默认小写开头
//XiaoMing——>xiaoMing
XiaoMing xiaoMing =(XiaoMing) context.getBean("xiaoMing");
xiaoMing.buyIpad();
xiaoMing.buyPhone();
}
}
产品:
@Component
public class HWProduct implements IProduct{
public void ipad() {
System.out.println("华为平板");
}
public void phone() {
System.out.println("华为手机");
}
}
注解:
- @Autowired 依赖注入(控制反转的关键)
- @Component 组件(标注的类相当于被管家管理的类)
- @ComponentScan 在启动过程Spring会去扫描Test类所在的包及子包,找到有@Component注解的类(相当于管家)
标注组件的注解除了 @Component还有:
- @Controller 一般用于标注控制器组件(Controller层)
- @Service 一般用于标注服务层组件(Service层)
- @Repository 一般用于标注持久层组件(DAO层)
如果产品中XMProduct也加入了 @Component
@Component
public class XMProduct implements IProduct{
public void ipad() {
System.out.println("小米平板");
}
public void phone() {
System.out.println("小米手机");
}
}
则会错误出现
这里说找到了两个产品,意思是不知道用哪一个。
这个时候我们可以指定注入依赖对象,在XiaoMing中加入: