IOC实现原理

一.为什么用IOC

IOC控制反转 ,目的为了让我们编写出更加松耦合,更加优雅的程序。传统的程序需要我们在类的内部显示的创建依赖对象。从而导致类与类之间的耦合度过高。,将对象的创建,查找依赖,以及生命周期的控制权交给了 Ioc 容器。对象之间
耦合较松,更加灵活。

二.IOC的实现原理

IOC实现的基础是工厂模式和反射机制

但是对于传统的工厂模式,如果增加新的水果类,就需要改动工厂类,采用反射的方式进行解决。

public static IFruit getInstance(String className) {
IFruit fruit = null;
try {
fruit = (IFruit) Class.forName(className).newInstance();//Class 类 的 forName 方法构造类的实例
//forName 返回与给定字符串名称的类或接口相关联的 类对象。
//newInstance 创建由此类对象表示的类的新实例。 该类被实例化为一个具有空参数列表的new表达式。 如果类尚未初始化,则初始化该类
}catch (Exception e) { e.printStackTrace();
}
return fruit; }
public static void main(String[] args) {
IFruit obj = null;
obj =
FruitFactoryByReflection.getInstance("com.bryantchang.reflectionTest.Ap
ple");
obj.eat();
}

但是我们不可能没错都知道完整的包名和类型啊!
这时候创建一个存放 bean 的资源文件

public class BeanResourceOps {
public static Properties getBeanProperties() throws IOException {
//Properties类表示一组持久的属性。 Properties可以保存到流中或从流中加载。 属性列表中的每个键及其对应的值都是一个字符串。 
Properties beanProperty = new Properties();
File beanResourceFile = new
File("/Users/TheBlindM/Desktop/work/meituan/codes/test_codes/personal_
growth/testJava/src/main/resources/fruit.properties");
if (beanResourceFile.exists()) {
beanProperty.load(new FileInputStream(beanResourceFile));
}else {
beanProperty.setProperty("apple",
"com.bryantchang.reflectionTest.Apple");
beanProperty.setProperty("orange",
"com.bryantchang.reflectionTest.Orange");
beanProperty.store(new FileOutputStream(beanResourceFile),
"fruit bean infos");
}
return beanProperty; } }

调用

public static void main(String[] args) throws IOException {
IFruit obj = null;
Properties fruitProperties = BeanResourceOps.getBeanProperties();
obj =
FruitFactoryByReflection.getInstance(fruitProperties.getProperty("apple
"));
obj.eat();
}

三.IOC容器初始化流程

接下来简要概括一下流程,具体源码可以去
IOC源码分析
1.Resource定位
创建 spring 容器时,通常要访问 XML 配置文件,除此之外还可以通过访问文件类型、
二进制流等方式访问资源,还有当需要网络上的资源时可以通过访问 URL,Spring 把这些
文件统称为 Resource。

FileSystemResource:以文件的绝对路径方式进行访问资源,效果类似于 Java 中的 File;
ClassPathResourcee:以类路径的方式访问资源,效果类似于

this.getClass().getResource("/").getPath();
2.通过返回的 resource 对象,进行 BeanDefinition 的载入
BeanDefinition 相当于一个数据结构,这个数据结构的生成过程是根据定位的
resource 资源对象中的 bean 而来的,这些 bean 在 Spirng IoC 容器内部表示成了的
BeanDefintion 这样的数据结构,IoC 容器对 bean 的管理和依赖注入的实现都是通过操
作 BeanDefinition 来进行的。
3.将 BeanDefiniton 注册到容器中
最终 Bean 配置会被解析成 BeanDefinition 并与 beanName,Alias 一同封装到
BeanDefinitionHolder 类中, 之后 beanFactory.registerBeanDefinition(beanName,
bdHolder.getBeanDefinition()),注册到
DefaultListableBeanFactory.beanDefinitionMap (ConcurrentHashMap)中。之后客户端如果要获取 Bean 对象,
Spring 容器会根据注册的 BeanDefinition 信息进行实例化。

四.详细初始化流程

在这里插入图片描述
1.)AbstractApplicationContext#refresh:此方法定义为模板方法(将部分方法延迟到子类实现),包含Spring容器启动的一系列工作。这里我们直接看obtainFreshBeanFactory方法,这是IoC容器初始化的入口。

2.)AbstractApplicationContext#obtainFreshBeanFactory:调用refreshBeanFactory和getBeanFactory方法,重新获取一个新的BeanFactory实例。

3.)AbstractRefreshableApplicationContext#refreshBeanFactory:销毁原BeanFactory,新建DefaultListableBeanFactory实例,并对其进行一些初始化工作。

4.)AbstractXmlApplicationContext#loadBeanDefinitions:上一步创建BeanFactory实例之后,通过该BeanFactory创建XmlBeanDefinitionReader实例,也就是ApplicationContext上下文将BeanDefinition的定位加载工作交付到了XmlBeanDefinitionReader。继续跟到重载的同名方法loadBeanDefinitions(XmlBeanDefinitionReader reader),这一步完成了将部分XML文件资源封装为Resource对象,而用户以XML文件路径传入的BeanDefinition资源文件也会在AbstractBeanDefinitionReader#loadBeanDefinitions(String…locations)逐一封装为Resource对象,并进行进一步的处理。

以上 1.) ~ 4.)步完成了Resource定位的工作。

5.)继续跟踪到XmlBeanDefinitionReader#loadBeanDefinitions:这一步主要是通过Resource对象获取XML文件的输入流,继续执行doLoadBeanDefinitions。因为是XML文件格式组织的BeanDefinition,因此AbstractBeanDefinitionReader需要委托到其子类XmlBeanDefinitionReader。

6.)XmlBeanDefinitionReader#doLoadBeanDefinitions:通过上一步获取到的输入流和Resource对象,获取Document对象。

7.)XmlBeanDefinitionReader#registerBeanDefinitions:初始化DefaultBeanDefinitionDocumentReader对象,将上一步得到的Document对象交由DefaultBeanDefinitionDocumentReader对象解析,并统计解析的BeanDefinition个数。

8.)DefaultBeanDefinitionDocumentReader#registerBeanDefinitions:获取Document对象的根元素,执行doRegisterBeanDefinitions。

9.)继续跟到DefaultBeanDefinitionDocumentReader#parseBeanDefinitions:初始化BeanDefinitionParserDelegate实例,递归解析Document。DefaultBeanDefinitionDocumentReader负责读入Document对象,实际将Document解析为BeanDefinition的却是BeanDefinitionParserDelegate对象。

10.)继续跟到DefaultBeanDefinitionDocumentReader#processBeanDefinition:传入Document对象的单个Element元素,将其交由上一步的BeanDefinitionParserDelegate对象解析,解析后得到BeanDefinitionHolder对象。解析过程较为复杂,有兴趣可以自行跟踪。

以上 5.) ~10.)步完成了BeanDefinition的载入工作,得到BeanDefinitionHolder对象。

11.)顺着DefaultBeanDefinitionDocumentReader#processBeanDefinition继续往下看,跟到BeanDefinitionReaderUtils#

registerBeanDefinition。传入上一步的BeanDefinitionHolder对象,将BeanDefinition注册到IoC容器中。

以上11.)完成的是向IoC容器注册这些BeanDefinition,BeanFactory是以Map的结构组织这些BeanDefinition的。可以在DefaultListableBeanFactory中看到此Map的定义。

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
以上就是Spring IoC容器的整个启动过程,这里完成的仅仅是BeanDefinition的载入和注册,Javabean之间的依赖关系并不会在初始化的时候完成!
————————————————

借鉴了该博客的部分内容 https://blog.csdn.net/sinat_34596644/article/details/80394209

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring的IOC(Inverse of Control)实现原理是通过IOC容器来实现的。IOC容器负责实例化、定位、配置应用程序中的对象,并建立这些对象间的依赖关系,从而实现对象之间的松耦合。 在Spring中,通过配置文件或注解的方式告诉Spring哪些Bean需要进行管理,Spring会根据配置文件或注解来实例化这些Bean,并将它们放入IOC容器中。当我们需要使用这些Bean时,只需从IOC容器中获取即可,而不需要手动创建对象。这样就实现了将控制对象创建的过程反转给Spring容器来管理的效果。 Spring的IOC容器充当了一个类似于餐馆的角色,我们只需要告诉Spring哪些Bean需要进行管理,然后通过指定的方式从IOC容器中获取相应的Bean。Spring提供了多种类型的IOC容器,例如基于XML配置的ApplicationContext,基于注解的AnnotationConfigApplicationContext等等。无论使用哪种类型的IOC容器,Spring都会负责创建和管理Bean的生命周期,并根据依赖关系进行自动注入。 总结来说,Spring的IOC实现原理是通过IOC容器管理Bean的实例化、定位和配置,实现对象之间的解耦,并提供便利的方式来获取和使用这些Bean。通过IOC容器,我们可以更加灵活地组织和管理应用程序的对象。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [springIoc实现原理](https://download.csdn.net/download/zhangcongyi420/11131211)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [一文带你深入剖析Spring IOC 实现原理](https://blog.csdn.net/SQY0809/article/details/118678588)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值