前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试系列-spring-ioc原理

面试系列-spring-ioc原理

作者头像
用户4283147
发布2022-10-27 15:53:29
3090
发布2022-10-27 15:53:29
举报
文章被收录于专栏:对线JAVA面试对线JAVA面试

低级容器BeanFactory

低级容器BeanFactory可以理解为就是个HashMap,Key是BeanName,Value是Bean实例,通常只提供注册(put),获取(get)这两个功能;是IOC容器的基础接口,所有的容器都是从它这里继承实现而来,BeanFactory作为SpringIOC容器,管理着Bean的生命周期,控制着Bean的依赖注入;

它实现的核心功能就是根据名称或类型来返回一个bean实例,一个工厂如果要具备这种功能它需要具备以下几个条件:

  • 持有各种bean的定义,只有拿到了bean的定义信息,才能根据这些信息进行实例化;
  • 持有各种bean之间的依赖关系,如果一个类中持有对另一个类的引用,那么在对该类进行实例化时,必须根据类之间的依赖关系对相关类也进行实例化,因此工厂必须获得类之间的依赖关系,否则无法正确实例化;

以上两种信息都依赖于我们的配置信息定义,比如xml配置文件,工厂需要一个工具来读取配置文件的信息,配置方式可以有:在XML中进行显式配置;在Java中进行显式配置;注解方式;

类的依赖关系通过注入方式实现:Spring提供了三种注入方式:构造方法注入;setter方法注入;注解方式注入;类的依赖关系及bean的属性定义保存在BeanDefinition(加载所有的Bean配置成BeanDefinition到容器中,如果Bean有依赖关系,则使用占位符暂时代替);

调用BeanFactory.getBean的时候,从BeanDefinition所属的Map里,拿出Class对象进行实例化,同时如果有依赖关系,将递归调用(原因:因为加载的顺序不同,很可能Bean_A依赖的Bean_B还没有加载好,也就无法从容器中获取)getBean方法(即如果碰到了属性是ref的(占位符),那么就从容器里获取这个Bean)——完成依赖注入;

高级容器ApplicationContext

比BeanFactory多了更多的功能,定义了一个refresh方法,用于刷新整个容器,即重新加载/刷新所有的bean;

  • BeanFactory:能够管理和装配Bean;
  • ResourcePatternResolver:能够加载资源文件;
代码语言:javascript
复制
//AnnotatinonConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文;
ApplicationContext context = new AnnotatinonConfigApplicationContext(com.cmos.DemoConfig.class);
//AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载SpringWeb应用上下文。
ApplicationContext context = new ClassPathXmlApplicationContext("demo.xml");
//ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源
//FileSystemXmlApplicationContext:从文件系统下的一个或多个XML配置文件中加载上下文定义;
ApplicationContext context = new FileSystemXmlApplicationContext("c:/demo.xml");
XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义;
  • MessageResource:能够实现国际化等功能;
  • ApplicationEventPublisher:能够注册监听器,实现监听机制;

refresh()方法里列出了IOC容器初始化的步骤,第一个方法是初始化准备,这里只是设置启动日期和活动标识以及执行属性源的初始化,走到抽象方法refreshBeanFactory(),IOC容器开始初始化,第一步先判断有没有现有的工厂,有的话就销毁掉,然后创建一个默认的工厂,也就是DefaultListableBeanFactory ,接下来两行代码是设置bean工厂的一些属性,注意看loadBeanDefinitions(beanFactory)这行,当创建了一个默认的bean工厂后,加载bean定义,首先定义了一个Reader,这个Reader就是用来读取xml配置文件,spring将资源返回的输入流包装以后传给了doLoadBeanDefinitions()方法,spring将包装的输入流解析成DOM文档,然后将DOM中包含的bean定义信息注册到IOC容器持有的Map<String,BeanDefinition>对象中,只要IOC容器持有了bean定义,就能正确的生产bean实例;

注:代码省略

Spring容器加载配置完整Bean

  1. ResourceLoader从存储介质中加载Spring配置信息,并使用Resource表示这个配置文件的资源;
  2. BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中每一个<bean>解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中;
  3. 容器扫描BeanDefinitionRegistry中的BeanDefinition,使用Java的反射机制自动识别出Bean工厂后处理后器(实现BeanFactoryPostProcessor接口)的Bean,然后调用这些Bean工厂后处理器对BeanDefinitionRegistry中的BeanDefinition进行加工处理,主要完成以下两项工作:
  • 对使用到占位符的<bean>元素标签进行解析,得到最终的配置值,这意味对一些半成品式的BeanDefinition对象进行加工处理并得到成品的BeanDefinition对象;
  • 对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过Java反射机制找出所有属性编辑器的Bean(实现java.beans.PropertyEditor接口的Bean),并自动将它们注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistry);
  1. Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition,并调用InstantiationStrategy着手进行Bean实例化的工作;
  2. 在实例化Bean时,Spring容器使用BeanWrapper对Bean进行封装,BeanWrapper提供了很多以Java反射机制操作Bean的方法,它将结合该Bean的BeanDefinition以及容器中属性编辑器,完成Bean属性的设置工作;
  3. 利用容器中注册的Bean后处理器(实现BeanPostProcessor接口的Bean)对已经完成属性设置工作的Bean进行后续加工,直接装配出一个准备就绪的Bean;
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 对线JAVA面试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 低级容器BeanFactory
  • 高级容器ApplicationContext
  • Spring容器加载配置完整Bean
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档