深入剖析Spring(二)——IoC容器的实现

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34173549/article/details/80382002 Sp...
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34173549/article/details/80382002

Spring的两种IoC容器

  • BeanFactory
    • 基础类型的IoC容器;
    • 采用延迟初始化策略(容器初始化完成后并不会创建bean的对象,只有当收到初始化请求时才进行初始化);
    • 由于延迟初始化,因此启动速度较快,占用资源较少;
  • ApplicationContext
    • 在BeanFactory的基础上,增加了更为高级的特定:事件发布、国际化等;
    • 在容器启动时便完成所有bean的创建;
    • 启动时间较长,占用资源更多;

IoC容器的主要类/接口介绍

title

  • BeanFactory
    它是一个接口,提供了获取容器中Bean的相关方法。

  • BeanDefinitionRegistry
    它才是IoC的容器,用于存储、管理所有的Bean对象。

  • DefaultListableBeanFactory
    它是IoC容器的一个具体实现,实现了BeanFactory和BeanDefinitionRegistry接口,因此既拥有管理Bean的容器,又拥有访问Bean的方法。

  • BeanDefinition
    每一个Bean都有一个BeanDefinition与之对应,用于存储Bean的相关信息:对象的class类型、是否是抽象类、构造方法参数等。
    RootBeanDefinition和ChildBeanDefinition是BeanDefinition的两个主要的实现类。

  • BeanDefinitionReader
    在Spring中,标注Bean的依赖关系有四中方式:

    1. 直接在代码中声明
    2. 通过XML文件声明
    3. 通过Properties文件声明
    4. 通过注解声明
      BeanDefinitionReader接口的作用就是读取配置文件中的bean信息,把它们解析成BeanDefinition对象,然后注册到BeanDefinitionRegistry中去。
      PropertiesBeanDefinitionReader和XmlBeanDefinitionReader是该接口的两个实现类,分别用于解析properties和xml格式的配置文件。
  • XmlBeanFactory
    它是一个集成了XmlBeanDefinitionReader功能的BeanFactory,用于简化初始化操作。

BeanFactory的两个重要阶段

  1. 容器启动阶段
    该阶段Spring会使用BeanDefinitionReader加载配置文件,并把所有的bean解析成BeanDefinition对象,并注册到BeanDefinitionRegistry。

  2. Bean实例化阶段
    对于BeanFactory容器,当调用者主动调用getBean方法或者因存在依赖关系容器隐式调用getBean时,如果当前Bean尚未初始化,或者bean配置成prototype,就会触发Bean实例的初始化。

BeanFactoryPostProcessor:一种容器扩展机制

Spring提供了BeanFactoryPostProcessor这种容器扩展机制,它允许我们在容器启动完成后、Bean实例化前插入额外的操作。
BeanFactoryPostProcessor提供了三个实现类:

1.PropertyPlaceholderConfigurer
一般情况下,我们并不会将数据库连接信息直接写死在dataSource这个bean中,而是将它们单独写在一个properties文件中,这样易于修改与阅读。而bean中使用占位符代替这些属性值,当容器启动完成后,在Bean初始化前用properties文件中的值替换占位符,再创建对象。
PropertyPlaceholderConfigurer就能实现这样的功能。

  • xml中作如下配置:
<bean id="dataSource" class="xxxxxx">
    <property name="url">
        <value>${jdbc.url}</value>
    </property>
    <property name="username">
        <value>${jdbc.username}</value>
    </property>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 使用properties文件存储属性值:
jdbc.url=jdbc:mysql://127.0.0.1:3306
jdbc.username=root
  • 1
  • 2

当容器启动完成后dataSource的BeanDefinition对象将会被注册进BeanDefinitionRegistry中,此时BeanDefinition中的属性值仍然是占位符的形式;接下俩,PropertyPlaceholderConfigurer就会发挥作用,它会将占位符用properties文件中的属性值替换掉。接下来bean就可以被正确地创建。

2.PropertyOverrideConfigurer
它的功能与PropertyPlaceholderConfigurer类似,也需要指定一个properties文件,只不过它会用配置文件中设置的那些bean的属性值替换指定bean的属性值。

  • xml中作如下配置:
<bean id="dataSource" class="xxxxxx">
    <property name="url">
        <value>jdbc:mysql://127.0.0.1:3306</value>
    </property>
    <property name="username">
        <value>chai</value>
    </property>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 使用properties文件存储属性值:
dataSource.url=jsbc:mysql://127.0.0.1:3307
dataSource.username=root
  • 1
  • 2

PropertyOverrideConfigurer会在容器启动完毕后、Bean对象创建之前,通过修改BeanDefinition对象,替换指定的属性值。
properties文件的内容必须遵循如下格式:

bean的名字.属性名=属性值
  • 1

3.CustomEditorConfigurer
该类用于向Spring容器增添自定义的PropertyEditor对象。

容器启动结束后bean创建之前,配置文件中所有的bean都被解析成BeanDefinition对象,该对象中关于bean所有的信息都是String类型的,若要创建bean对象,就需要将这些String类型的信息解析成它们原本的类型。在Spring中,每种类型都有对应一个PropertyEditor类,该类中封装了String与该类型的转换方法。当然,对于某些类型Spring并未提供相应的PropertyEditor时,我们可以自定义PropertyEditor,并使用CustomEditorConfigurer将其告诉Spring容器,让它在遇到该类型的时候采用我们自定义的PropertyEditor去解析。

Spring提供的部分PropertyEditor:

  • StringArrayPropertyEditor
    将字符串转换成String[],默认以,分割。
  • ClassEditor
    类似于Class.forname(String),将字符串转换成class对象。
  • FileEditor
    将字符串转换成File对象。
  • URLEditor
    将字符串转换成URL对象。
  • InputStreamEditor
    将字符串转换成InputStream对象。
  • LocaleEditor
    将字符串转换成Locale对象。
  • PatternEditor
    将字符串转换成Pattern对象。

以上类型的字符串,Spring会自动将它们转换成原本的类型。而我们自定义的PropertyEditor必须要通过CustomEditorConfigurer将其加入容器。

如何开启BeanFactoryPostProcessor功能?
1.BeanFactory

// 创建BeanFactory对象
ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory( new ClassPathResource("xxx") );
// 创建BeanFactoryPostProcessor对象
PropertyPlaceholderConfigurer processor = new PropertyPlaceholderConfigurer();
// 设置properties文件的位置
processor.setLocation("xxx");
// 将其传递给beanFactory
processor.postProcessBeanFactory(beanFactory);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.ApplicationContext
ApplicationContext会自动检测配置文件中出现的BeanFactoryPostProcessor,因此只需要在配置文件中声明所使用的BeanFactoryPostProcessor即可。

<bean class="xxxxx.PropertyPlaceholderConfigurer">
    <property>
        <list>
            <value>properties文件路径</value>
        </list>
    </property>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7


相关文章
|
3月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
3月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
467 2
|
7月前
|
XML 人工智能 Java
Spring IOC 到底是什么?
IOC(控制反转)是一种设计思想,主要用于解耦代码,简化依赖管理。其核心是将对象的创建和管理交给容器处理,而非由程序直接硬编码实现。通过IOC,开发者无需手动new对象,而是由框架负责实例化、装配和管理依赖对象。常见应用如Spring框架中的BeanFactory和ApplicationContext,它们实现了依赖注入和动态管理功能,提升了代码的灵活性与可维护性。
203 1
|
XML Java 数据格式
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
|
8月前
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
|
5月前
|
Kubernetes Docker Python
Docker 与 Kubernetes 容器化部署核心技术及企业级应用实践全方案解析
本文详解Docker与Kubernetes容器化技术,涵盖概念原理、环境搭建、镜像构建、应用部署及监控扩展,助你掌握企业级容器化方案,提升应用开发与运维效率。
880 108
|
6月前
|
存储 监控 测试技术
如何将现有的应用程序迁移到Docker容器中?
如何将现有的应用程序迁移到Docker容器中?
471 57