IOC(Inversion of Control)?
将设计好的对象移交给容器控制;反转:原来是通过new关键字主动获取依赖的对象,而IOC有专门的容器负责控制(创建、初始化、销毁)。
IoC 具体实现:依赖注入(DI(Dependency Injection)——组件之间的依赖关系有容器在运行时期决定,容器动态的将某一个依赖关系注入到组件之中)
【通俗理解一下,就是设计好了一批组件(类),他们之间可能互相会存在一定的组合依赖关系,比如其中一个类的成员是另一个类的引用,此时将这一批类注册(就是登记一下,声明类的具体位置,如何识别等等)到IOC容器,IOC容器会在运行程序的时候动态的将需要的对象注入相关的组件】
为什么使用?
- 实现组件之间解耦
- 提高程序的灵活性、可维护性、可拓展性
- 提升组件重用率
例子
1. 创建一个Maven Project工程,archetype选择quickstart:
创建Maven工程
2. 配置pom.xml:
在properties中添加Spring版本号
<spring.version>5.0.0.RELEASE</spring.version>
引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
3. 定义一个接口:
package ioctest;
/**
* @author 舟吉
* @create 2020-12-22
*/
public interface IAir {
}
4. 以下两个实现类实现接口:
package ioctest;
import org.springframework.stereotype.Component;
/**
* @author 舟吉
* @create 2020-12-22
*/
@Component
public class CleanAir implements IAir{
@Override
public String toString() {
// return super.toString();
return "CleanAir";
}
}
package ioctest;
import org.springframework.stereotype.Component;
/**
* @author 舟吉
* @create 2020-12-22
*/
@Component
public class DirtyAir implements IAir {
@Override
public String toString() {
// return super.toString();
return "DirtyAir";
}
}
5. 使用前面的类
package ioctest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
/**
* @author 舟吉
* @create 2020-12-22
*/
@Component
public class ErHa {
/*
*此处没有new一个CleanAir对象而是使用@Qualifier标记
*由IoC容器后面在运行时识别标识为cleanair的组件或者类并赋给这个构造器(依赖注入)
*/
@Autowired
public ErHa(@Qualifier("cleanair") IAir air){
this.air = air;
}
IAir air;//作为erha(二哈)的成员变量——>依赖
public void Breath(){
System.out.println(this.air.toString());
}
}
6. 在scr/main/resources下面新建一个ApplicationContext.xml(没有resources则新建一个对应的目录即可)
<?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"
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.xsd">
<!-- 配置组件 -->
<context:component-scan base-package="ioctest"/>
<bean id="CleanAir" class="ioctest.CleanAir">
<qualifier value="cleanair"></qualifier>
</bean>
<bean id="DirtyAir" class="ioctest.DirtyAir">
<qualifier value="dirtyAir"></qualifier>
</bean>
<bean id="erha" class="ioctest.ErHa"></bean>
</beans>
记录一个问题
#问题:expected single matching bean but found 2: cleanAir,CleanAir
@Component
public class ErHa {
@Autowired
public ErHa(@Qualifier("cleanAir") IAir air){//此处声明的Qualifier为cleanAir
this.air = air;
}
IAir air;
public void Breath(){
...
}
}
相关的配置文件声明如下,但是会出现之前的报错:
expected single matching bean but found 2: cleanAir,CleanAir
<bean id="CleanAir" class="ioctest.CleanAir">
<qualifier value="cleanAir"></qualifier>
</bean>
如果修改配置文件中的qualifier value为cleanair则正常运行
(此时无论是CleanAir还是cleanair都和注解所声明的cleanAir不相匹配)
<bean id="CleanAir" class="ioctest.CleanAir">
<qualifier value="cleanair"></qualifier>
</bean>