一、Spring容器核心类介绍及初始化流程

Spring容器简单使用与基本实现

Spring 发展迅迅速,早期的Spring仅指代Spring Framework基础框架,后来基于Spring Framewoek孵化出了大量的项目,Spring指代也变成了Spring家族(全家桶)。但这里说的Spring还是指代Spring Framework

Srping Framework框架架构图

spring-overview

Spring Framakework架构图来源于早期的Spring官网。

Spring框架由组织成大约20个模块的功能组成。这些模块分为核心容器、数据访问/集成、Web、AOP(面向方面编程)、检测、消息传递和测试。

从架构图可以看出Spring容器的其他模块都以核心容器作为基石进行实现,其中核心容器中的spring-core和 spring-beans模块提供了框架的基本部分,包括Spring容器(IOC)和依赖注入功能(DI)。 BeanFactory 是工厂模式的复杂实现。

Spring容器的基本使用

下面是基于spring-core和spring-bean对Spring容器的一个简单使用示例:

创建一个JavaBean

JavaBean

public class TestBean{
    private String testStr = "testStr";
    
    public String getTestStr() {
        return testStr;
    }

    public void setTestStr(String testStr) {
        this.testStr = testStr;
    }
    
}

创建配置文件

beanFactoryTest.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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="test class="com.zwx.bean.testBean"></bean>

</beans>

创建测试类

BeanFactoryTest

@SuppressWarnings("deprecation")
public class BeanFactoryTest {

    @Test
    public void testSimpleLoad() throws IOException {
        // 创建Spring容器BeanFactory实例
        BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
		// 从容器中获取配置类的实例
        testBean testBean = (testBean) bf.getBean("testBean");
        // 使用从容器中获取的配置类
        assertEquals("testStr",testBean.getTestStr());

    }
}

此处Spring容器实例用的BeanFactory,但大部分情况下使用的都是ApplicationContext

ApplicationContext在spring-context模块下。该模块继承了 Beans 模块的功能并进行了扩展,对国际化(例如使用资源包)、事件传播、资源加载以及通过 Servlet 容器透明创建上下文的支持。还支持 Java EE 功能,例如 EJB、JMX 和基本远程处理。ApplicationContext也是spring-context中的核心。

示例程序解析

接着简单分析一下Spring容器基本使用做了哪些事,又是怎么做的。

功能分析

  1. 读取配置文件beanFactoryTest.xml。
  2. 根据beanFactoryTest.xml中的配置找到对应的类的配置,进行实例化。
  3. 调用实例化后的示例。

如果需要我们自己去实现以上三个步骤,那我们可能会用到至少三个类进行实现:

  • ConfigReader:读取验证配置文件,将配置文件中配置好的内容读取解析出来,载入内存。
  • ReflectionUtil:根据配置文件中读取到的配置通过反射进行实例化。
  • App:将一系列操作进行串联

Spring核心类

如上所诉,我们可以通过简单的几个类就实现出这个功能,但是Spring庞大的体积告诉我们,事情显然没有这么简单,但和我们所想的实现显然思路是基本一致的,只是其中多了许多具体的细节处理,在我们迫不及待想要去看看Spring是如何进行实现之前,不妨先来看看Spring中的核心类。

核心类介绍

DefaultListableBeanFactory

DefaultListableBeanFactory是整个bean加载的核心,是Spring注册及加载bean的默认实现。

XmlBeanFactory继承于DefaultListableBeanFactory,XmlBeanFactory对DefaultListableBeanFactory不同的地方其实是在XmlBeanFactory中使用了自定义的XML读取器XmlBeanDefinitionReader,实现了个性化的BeanDefinition读取。

DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory并实现了ConfigurableListableBeanFactory以及BeanDefinitionRegistry接口。

结构图

DefaultListableBeanFactory层次结构图

容器加载相关类图

容器加载相关类图

根据以上的类图以及层次结构图,可以很清晰地从全局角度了解DefaultListableBeanFactory的脉络。

简单介绍一下这些类的作用:

  • AliasRegistry:定义对alias(别名)的简单增删改查等操作。
  • SimpleAliasRegistry:主要使用map作为alias的缓存,并对接口AliasRegistry进行实现。
  • SingletonBeanRegistry:定义对单例的注册及获取。
  • BeanFactory:定义获取bean及bean的各种属性。
  • DefaultSingletonBeanRegistry:对接口SingletonBeanRfgistry各函数的实现。
  • HierachicalBeanFactory:继承BeanFactory,也就是在BeanFactory定义的功能的基础上增加了parentFactory支持。
  • BeanDefinitionRegistry:定义对BeanDefinition的各种增删改查。
  • FactoryBeanRegistrySupport:在DefaultSingletonBeanRegistry基础上增加了对FactoryBean的特殊处理功能。
  • ConfigurableBeanFactory:提供配置Factory的各种方法。
  • ListableBeanFactory:根据各种条件获取bean的配置清单。
  • AbstarctBeanFactory:综合FactoryBeanRegistrySupport和ConfigurableBeanFactory的功能。
  • AutowireCapableBeanFactory:提供创建bean、自动注入、初始化以及应用bean的后处理器。
  • AbstractAutowireCapableBeanFactory:综合AbstractBeanFactory并对接口AutowireCapableBeanFactory进行实现。
  • ConfigurableListableBeanFactory:BeanFactory配置清单,指定忽略类型及接口等。
  • DefaultListableBeanFactory:综合上面所有功能,主要是对bean注册后的处理。

XmlBeanFactory对DefaultListableBeanFactory类进行了扩展,主要用于从XML文档中读取BeanDefinition,对于注册及获取bean都是使用从父类DefaultListableBeanFactory继承的方法去实现,而唯独与父类不同的个性化实现就是增加了XmlBeanDefinitionReader类型的reader属性。

在XmlBeanFactory中主要使用reader属性对资源文件进行读取和注册。

XmlBeanDefinitionReader

XML配置文件的读取是Spring中重要的功能,因为Spring的大部分功能都是以配置作为切入点的,我们可以从XmlBeanDefinitionReader中梳理一下资源文件读取、解析及注册的大致脉络。

配置文件读取相关类图

配置文件读取相关类图

上图为XML配置文件读取的大致流程。

简单介绍一下这些类的作用:

  • ResourceLoader:定义资源加载器,主要应用于根据给定的资源文件地址返回对应的Resource。
  • BeanDefinitionReader:主要定义资源文件读取并转换为BeanDefinition的功能。
  • EnvironmentCapable:定义获取Enviroment方法。
  • DocumentLoader:定义从资源文件加载到转换为Document的功能。
  • AbstractBeanDefinitionReader:对EnvironmentCapable、BeanDefinitionReader类定义的功能进行实现。
  • BeanDefinitionDocumentReader:定义读取Document并注册BeanDefinition功能。
  • BeanDefinitionParserDelegate:定义解析Element的各种方法。

在XmlBeanDefinitionReader中主要包含几步处理:

  1. 通过继承自AbstractBeanDefinitionReader中的方法,来使用ResourceLoader将资源文件路径转换为对应的Resource文件。
  2. 通过DoucumentLoader对Resource文件进行转换,将Resource文件转换为Document文件。
  3. 通过实现接口BeanDefinitionDocumentReader的DefaultBeanDefinitionDocumentReader类对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。

XmlBeanFactory初始化流程

介绍完Spring容器中的核心类后,我们再次转移思绪来到具体上面来,首先便从示例程序中实例化容器开始。

示例程序测试类中通过以下代码来进行容器的实例化:

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));

这段示例测试代码我们提过是用来加载配置文件并根据配置文件内容初始化Spring容器的,我们根据下面的XmlBeanFactory初始化时序图一起来看一下这句代码的执行逻辑。

XmlBeanFactory初始化时序图

XmlBeanFactory初始化时序图

通过时序图我们不难看出,在测试类BeanFactoryTest类中首先调用ClasspathResource的构造函数来构造Resource资源文件的实例化对象。随后后续的资源就可以使用Resource提供的各种服务来进行操作了,当我们获取Resource实例化对象后,就可以进行XmlBeanFactory的初始化了。

既然Spring的配置文件是通过ClassPathResource来进行封装的,new ClassPathResource("beanFactoryTest.xml");那ClassPathResource又做了些什么呢?以及Spring到底是如何处理不同来源的资源文件处理的呢?


posted @ 2023-09-13 21:36  困意总是偷袭我  阅读(38)  评论(0)    收藏  举报