什么是IoC
所谓的控制反转(Inversion of Control),缩写为IoC,其实就是把对象的创建和对象之间的依赖关系处理,交给 Spring容器来管理,不用程序员自己创建和维护的一种技术。我们使用IoC的目的,主要是为了降低类之间的耦合。
IoC的底层原理
IoC的底层原理主要是基于xml解析+工厂模式+反射等技术进行实现。
- xml解析:基于xml,配置好要创建的Javabean对象;
- 工厂模式:把对类的创建初始化等工作,全都交给一个工厂来执行;
- 反射:使用反射技术创建xml中配置的bean。
IoC模拟实现
为了让大家更好地理解IoC的工作原理,接下来我们自己简单模拟一下Spring IoC的底层实现原理。
第一步:我们先准备一个属性文件beans.properties,我这里使用属性文件代替xml的文件功能。
dept=com.qfedu.pojo.Dept
emp=com.qfedu.pojo.Emp
第二步:编写工厂类QfBeanFactory.java
/**
* 模拟spring 容器的工厂类
*/
public class QfBeanFactory {
private static Properties properties = new Properties();
//该map相当于spring容器,用来存储创建好的bean对象
private static Map<String, Object> ioc = new HashMap<String, Object>();
static {
try {
properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("beans.properties"));
//获取所有属性名
Set<String> names = properties.stringPropertyNames();
System.out.println(names);
//通过反射技术创建属性文件里配置的要创建的bean开始
for (String name : names) {
//获取全类名
String clsName= (String) properties.get(name);
Class clazz=Class.forName(clsName);
if (!Objects.isNull(clazz)){
//反射构建对象
Object object=clazz.getConstructor().newInstance();
// 存储到map中
ioc.put(name,object);
}
}
//通过反射技术创建属性文件里配置的要创建的bean结束
} catch (Exception e) {
e.printStackTrace();
}
}
/**
通过属性文件中属性名(类似spring配置文件中的bean的id)获取工厂创建好的对象
*/
public static Object getBean(String beanName){
return ioc.get(beanName);
}
}
代码解释:
- 工厂类中的静态代码块实现读取属性文件中的配置信息;
- 根据读到的配置信息,使用反射技术构建bean对象;
- 然后将构建好的对象放到map中;
- 通过提供的getBean方法,获取工厂中创建好的bean对象。
第三步:我们再编写一个测试类:
public class IocTest{
public static void main(String[] args) {
Dept dept= (Dept)QfBeanFactory.getBean("dept");
System.out.println(dept);
Emp emp= (Emp)QfBeanFactory.getBean("emp");
System.out.println(emp);
}
}
经过以上测试我们可以获得创建好的dept和emp对象,以上我们模拟了spring ioc的原理。
bean对象的创建
接下来我们再来看看Spring框架又是怎么创建和使用bean对象的。
4.1 创建spring-bean.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dept" class="com.qfedu.pojo.Dept"></bean>
<bean id="emp" class="com.qfedu.pojo.Emp"></bean>
</beans>
4.2 加载配置文件获得Spring IoC容器
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-bean.xml");
4.3 通过spring容器获取dept、emp 对象
Emp emp= (Emp) applicationContext.getBean("emp");
System.out.println(emp);
Dept dept= (Dept) applicationContext.getBean("dept");
System.out.println(dept);
4.4 小结
最后我们再总结一下Spring创建bean对象的过程。
- spring-bean.xml相当于beans.properties;
- ClassPathXmlApplicationContext就相当于QfBeanFactory;
- getBean 方法相当于QfBeanFactory中的getBean。
其中ClassPathXmlApplicationContext类的结构图如下所示:
通过以上类结构图,我们可以看出ClassPathXmlApplicationContext的最顶层就是BeanFacorty工厂,而ClassPathXmlApplicationContext则是一个具体的实现类。BeanFacorty有很多实现类,其中ClassPathXmlApplicationContext、AnnotationConfigApplicationContext则是比较常用的具体子类。
BeanFactory以Factory结尾,表示这是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括实例化、定位、配置应用程序中的对象及建立这些对象间的依赖等。BeanFactory只是个接口,并不是IoC容器的具体实现,所以Spring容器给出了多种实现,如 ClassPathXmlApplicationContext、AnnotationConfigApplicationContext、ApplicationContext等。
现在你知道Spring是怎么实现IoC的了吗?如果你还有什么疑问,可以在评论区留言哦。关注千锋官方博客,干货天天都不断哦!
版权归原作者 千锋教育官方 所有, 如有侵权,请联系我们删除。