容器的基本实现
首先查看小例子:
项目结构:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>learn</groupId>
<artifactId>spring-resource</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<description>spring 源码阅读</description>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
</dependencies>
</project>
public class TestBean01 {
public String getHello() {
return "hello spring";
}
}
@SuppressWarnings("deprecation")
public class BeanFactoryTest01 {
public static void main(String[] args) {
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("BeanFactoryTest01.xml"));
TestBean01 test=(TestBean01) bf.getBean("testBean");
System.out.println(test.getHello());
}
}
<?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-3.0.xsd">
<!-- 配置需要被Spring管理的Bean(创建,创建后放在了Spring IOC容器里面) -->
<bean id="testBean" class="char02.TestBean01"></bean>
</beans>
现在 BeanFactory 已经很少使用了而是使用 ApplicationContext
功能分析:
- 首先读取配置文件
- 实例化读到的类
- 调用类的方法
ConfigReader 用于读取已经验证配置文件。
Reflection 用于反射实例化。
源码分析 :
首先是beans 的依赖:
UML图:
DefaultListableBeanFactory
XmlBeanFactory 继承自DefaultListableBeanFactory。而DefaultListableBeanFactory是整个bean加载的核心部分。是Spring中注册以及加载bean的默认实现。而XmlBeanFactory 与DefaultListableBeanFactory 的区别是XmlBeanFactory实现了自定义的一个xml文件读取器 XmlBeanDefinitionReader实现了个性化的BeanDefinitionReader 读取。下面是ConfigurableListableBeanFactory的层级结构图。
此图包含实现的接口:
先了解一下各个类的用法:
- AliasRegistry:定义对alias的简单增删改等操作
- SimpleAliasRegistry: 只要使用map作为alias的缓存并对AliasRegistry进行实现
- SingletonBeanRegistry:定义对单例的注册以及获取。
- BeanFactory:定义获取bean以及bean的各种属性。
- DefaultSingletonBeanRegistry:对接口SingletonBeanRegistry的各个方法的实现。
- HierarchicalBeanFactory:继承BeanFactory,也就是在BeanFactory的定义的功能的基础上增加对parentFactory的支持。
- BeanDefinitionRegistry: 定义对BeanDefinition的各种增删改操作。
- FactoryBeanRegistrySupport:在DefaultSingletonBeanRegistry基础上增加了对FactoryBean(?)的特殊处理。
- ConfigurableBeanFactory:提供配置Factory的各种方法
- ListableBeanFactory:根据各种条件获取bean的配置清单
- AbstractBeanFactory:综合FactoryBeanRegistrySupport和ConfigurableBeanFactory 的功能
- AutowireCapableBeanFactory:提供创建bean、自动注入、初始化、已经应用bean的后处理器
- AbstractAutowireCapableBeanFactory:综合AbstractBeanFactory并对AutowireCapableBeanFactory进行实现。
- ConfigurableListableBeanFactory:BeanFactory配置清单、指定忽略类型及接口
- DefaultListableBeanFactory:综合以上所有功能,只要是对bean注册后的处理。
XmlBeanFactory 是对DefaultListableBeanFactory的拓展主要是从Xml中读取BeanDefinitionReader
BeanDefinitionReader 接口层次:
BeanDefinitionReader
xml配置文件的读取是spring中的一个重要的功能。那么XmlBeanDefinitionReader 梳理一下资源文件读取、解析已经注册的大致脉络。
首先肯看各个类的功能:
- ResourceLoader: 定义资源加载器,主要是对给定资源地址返回相应的Resource
- BeanDefinitionReader:主要定义资源读取并装换为BeanDefinition的各个功能。
- EnvironmentCapable :定义获取Environment 的方法。
- DocumentLoader: 定义从资源文件加载到转换成Document的方法
- AbstractBeanDefinitionReader:对EnvironmentCapable、BeanDefinitionReader类定义功能的实现。
- BeanDefinitionDocumentReader:定义读取Document并注册BeanDefinition 功能
- BeanDefinitionParserDelegate: 定义解析各个Element的各种方法。
- XmlBeanDefinitionReader:的结构层次图:
- XmlBeanDefinitionReader 运行流程:
- 通过继承的AbstractBeanDefinitionReader中的ResouceLoader 将资源转换成Resouce
- DocumentLoader 对Resouce文件进行装换,转换成Document
- 通过BeanDefinitionDocumentReader对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。
看到这里我相信很多人都懵逼
**接下来细讲 例子中代码的详细实现功能 **
- 配置文件的封装
配置文件是通过 ClassPathResource进行封装的。ClassPathResouce完成了一个什么样的功能呢?
spring定义了自己的Resource接口来封装底层资源。
- Resoucre 的结构层次:
- InputStreamResource:
- Resource:
- AbstractResource:
此类提供了Resouce定义的一些方法的实现:
- 然后直接看待 ClassPathResource :
对应代码举例子中的 初始化一个Resouce:new ClassPathResource("BeanFactoryTest01.xml") 查看它做了哪些操作:
现在已经构建好了一个Resouce
继续查看XmlBeanFactory的代码的定义:
查看加载配置的实现:
这里还可以看见日志的打印:和控制台输出的对应。 在加载配置文件时候 Resource被装换成了 EncodedResource
加载配置类的实现:
其中从ClassPathResource获取InputStream的实现: