spring框架四个基础核心一(IOC容器)

1.引言

spring框架有四个基础核心:

  • IoC容器
  • JavaConfig
  • 事件监听
  • Spring factories

从本篇文章开始,我会依次给你分享关于四个基础核心的相关知识。开始吧!

2.IoC容器

2.1.什么是IOC容器

可以把spring IoC容器,看做一家餐馆,你到餐馆点菜,你只关心最终吃到这道菜,至于菜需要用什么原料?怎么做?你其实是不关心的。

同理,回到技术术语,当你在使用IoC容器的时候,你只关心需要什么bean对象,至于这个bean对象是怎么实例化的?依赖了什么组件?你其实是不关心的。

好了,那么到底什么是IoC呢?它的英文名称是Inversion of Control,即控制反转。控制反转有点抽象,我给你举个例子,你大概就懂了。

  • 在没有spring框架以前,程序代码中,当需要某个对象的时候,通常需要new 的方式来获取对象,并且通过构造方法,或者set方法处理对象之间的依赖关系。关键词:这里是写程序的人,在控制管理对象
  • 在有了spring框架后,程序代码中,当需要某个对象的时候,通常从ApplicationContext中获取对象,至于这个对象怎么初始化的?怎么完成组件依赖的?统统不用关心,spring框架提供了一系列工厂来管理这些bean对象。

也就是说,需要的bean对象原来是由你来new,你来管理,转变成交给spring框架来管理,对象的控制权由你,转移给了spring框架,这就是控制反转!

那么这里的IoC容器,其实就是一个Map,后面我们会继续解密。暂且按下不表。

当然了,一家餐馆要做出美味佳肴,原料和菜谱是必不可少的。IoC容器一样,要管理bean对象和它们之间的依赖关系,需要有相应的原材料和菜谱。

xml 复制代码
<bean id="a" class="com.xxx.A">
    <property name="b" ref="b">
</bean>

早期spring框架的玩家,对上面这个配置一定不会陌生!通过bean标签配置了一个bean,通过property属性标签,说明a对象,依赖一个b对象。这些是开发通过配置告诉spring框架,来,这就是原材料。

自然spring框架需要有与配置相应的原材料表示,这就是BeanDefinition。该实例负责bean对象的全部必要信息,包括:Class、访问控制、构造方法、参数、属性等。

原材料有了,菜谱呢?对应的菜谱是BeanDefinitionRegistry,和BeanFactory。BeanDefinitionRegistry负责抽象bean注册逻辑。Beanfactory负责抽象bean管理逻辑。配合起来天衣无缝!

  • BeanFactory核心方法
  • BeanDefinitionRegistry核心方法

且它们有一个共同的杰出后代:DefaultListableBeanFactory。作为默认的容器实现,同时实现了BeanDefinitionRegistry和BeanFactory,因此它同时负责bean的注册,管理工作。上一个图,直观一些。

了解了IoC相关的概念,再来看IoC的大致工作流程,主要有两个阶段。

2.2.IOC容器工作流程

  • 启动阶段

我们知道,要让容器管理bean对象,需要告诉容器相关的原材料信息,在实际开发中通常是你我提供的配置信息,比如xml配置或者注解配置,这些信息统称为Configuration MetaData,即配置元数据。

在spring 框架中,负责这个事情的是BeanDefinitionReader,该类负责加载、解析、分析Configuration MetaData信息,将这些信息封装成BeanDefinition,并注册到BeanDefinitionRegistry。这样一来启动阶段就算完成了。

  • bean实例化阶段

经过启动阶段,原材料准备好。当有某个使用方通过BeanFactory的getBean方法,获取某个bean对象时,容器会检查目标bean对象之前是否已经实例化。

如果有,则直接返回给使用方;

如果没有,则进入bean的实例化,容器会根据注册的BeanDefinition进行实例化,并为其注入依赖。实例化完成,返回给使用方。

需要注意的是,我们一直在说BeanFactory,事实上在实际应用中,用的更多的是另外一个容器实现:ApplicationContext。ApplicationContext是扩展至BeanFactory。它们两的区别在于:BeanFactory是延迟加载,而ApplicationContext是饥饿加载。

2.3.容器扩展机制

在整个spring容器管理bean生命周期过程中,不同阶段提供了对应的扩展点,这些扩展点使得我们在使用spring框架时,具备足够的灵活性。

在启动阶段,BeanFactoryPostProcessor可以在容器实例化对象之前,对注册到容器中的BeanDefinition对象进行修改,然后改变bean对象的行为。

要想自定义扩展类,需要实现接口BeanFactoryPostProcessor。实际应用中,你可能会需要自定义扩展多个BeanFactoryPostProcessor,为了保障多个BeanFactoryPostProcessor执行顺序,通常还需要扩展实现Ordered接口。

spring为我们提供了一个示例扩展:PropertyPlaceholderConfigurer。你一定还有这样的印象,在项目开发中,很多配置信息为了方便统一管理,在引用的地方,是这样的

xml 复制代码
${jdbc.driver}
${jdbc.url}
${jdbc.username}
${jdbc.passwd}

这些配置信息,在BeanDefinition对象中,是以占位符的形式存在。但当BeanFactory需要真正实例化bean对象时,需要将占位符替换成具体的配置信息。这个活谁来负责?没错,就是PropertyPlaceholderConfigurer。

相比较在启动阶段的扩展,大多数同学可能更熟悉BeanPostProcessor。BeanFactoryPostProcessor负责扩展bean定义;而BeanPostProcessor负责扩展实例化后的bean。它有两个方法:

  • postProcessBeforeInitialization:前置处理(执行初始化),即通常意义的init-method前
  • postProcessAfterInitialization:后置处理(销毁),即通常意义的destroy-method后

在实际应用中,你可以自定义一个注解,在某个bean上加上该注解,然后在BeanPostProcessor中检查该对象上,是否有注解?如果有,你便可以为所欲为的进行扩展!是不是很happy!

看一个spring框架提供的例子,经常能够看到各种Aware接口,它们的作用是在对象实例化完成以后,将Aware接口中定义的依赖注入到当前实例中,Aware的意思即注入,前面是什么,就注入什么。

比如ApplicationContextAware接口,如果你需要在你的bean对象中,获取到ApplicationContext对象,你只需要让你的bean实现ApplicationContextAware接口,则万事大吉!

相关推荐
豌豆花下猫5 分钟前
Python 3.14 新特性盘点,更新了些什么?
后端·python·ai
caihuayuan537 分钟前
Vue生命周期&脚手架工程&Element-UI
java·大数据·spring boot·后端·课程设计
MaCa .BaKa2 小时前
37-智慧医疗服务平台(在线接诊/问诊)
java·vue.js·spring boot·tomcat·vue·maven
八股文领域大手子2 小时前
Spring Boot Controller 如何处理HTTP请求体
java·开发语言·sql·spring·spring cloud
tanxiaomi2 小时前
Java中对象集合转换的优雅实现【实体属性范围缩小为vo】:ListUtil.convert方法详解
java·spring boot·mybatis
小刘|2 小时前
Spring,SpringMVC,SpringBoot,SpringCloud的区别
spring boot·spring·spring cloud
明月与玄武3 小时前
Spring Boot中的拦截器!
java·spring boot·后端
为美好的生活献上中指3 小时前
java每日精进 5.07【框架之数据权限】
java·开发语言·mysql·spring·spring cloud·数据权限
菲兹园长4 小时前
SpringBoot统一功能处理
java·spring boot·后端
muxue1784 小时前
go语言封装、继承与多态:
开发语言·后端·golang