Spring Bean加载流程分析(通过 XML 方式加载)( 三 )
通过该行代码 , 我们定义了一个 Bean 定义的读取器 , 将第二步生成的 defaultListableBeanFactory 对象传入我们定义的读取器 。
/** * Create new XmlBeanDefinitionReader for the given bean factory. * @param registry the BeanFactory to load bean definitions into, * in the form of a BeanDefinitionRegistry */public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {super(registry);}复制代码
该方法是为给定的 BeanFactory 创建一个 BeanDefinitionReader 。 这里我们可以看到构造方法的入参类型是 BeanDefinitionRegistry 类型 , 为什么我们定义的 DefaultListableBeanFactory 也能传入进去?很显然我们的 DefaultListableBeanFactory 实现了该接口 。 我们看看 DefaultListBeanFactory 的继承图 。
文章插图
XMLBeanDefinitionReader 的构造方法调用了父类的构造方法 , 跟进去父类的构造方法看看 。
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");this.registry = registry;// Determine ResourceLoader to use. 决定要使用的 ResourceLoader// 1. 根据传入进来的 BeanDefinitionRegistry 来获取 ResourceLoaderif (this.registry instanceof ResourceLoader) {this.resourceLoader = (ResourceLoader) this.registry;} else {this.resourceLoader = new PathMatchingResourcePatternResolver();}// Inherit Environment if possible 继承环境如果存在的话// 2. 根据传入进来的 BeanDefinitionRegistry 来获取当前的环境if (this.registry instanceof EnvironmentCapable) {this.environment = ((EnvironmentCapable) this.registry).getEnvironment();} else {this.environment = new StandardEnvironment();}}复制代码
该构造方法做了如下的几件事情
- 给当前类的 registry 类型赋值
- 根据传入进来的参数来获取对象的 ResourceLoader
- 根据传入进来的参数来获取当前的环境
public PathMatchingResourcePatternResolver() {this.resourceLoader = new DefaultResourceLoader();}复制代码
显然传入进来的 BeanDefinitionRegistry 不是 ResourceLoader 的实现类 , 这个我们从类的继承图中可以看出来 。 因此当前类的 ResourceLoader 为 new PathMatchingResourcePatternResolver(); , 该方法获取了默认的 ResourceLoader 。public PathMatchingResourcePatternResolver() {this.resourceLoader = new DefaultResourceLoader();}public DefaultResourceLoader() {// 返回了一个默认的 ResourceLoader , 并且赋值当前类的 classLoaderthis.classLoader = ClassUtils.getDefaultClassLoader();}复制代码
前面做了这么多的准备工作 , 接下来开始真正从我们定义好的 applicationContext.xml 来加载 Bean 的定义 。 该功能通过 beanDefinitionReader.loadBeanDefinitions(resource); 来实现 。4. 从给定的资源文件中加载 BeanDefinition看看 beanDefinitionReader.loadBeanDefinitions(resource); 是如何加载 Bean 的定义的 。
Spring 对方法名称的命名比较有讲究 , 基本上可以做到见名之意 。 通过方法名我们就可以知道 loadBeanDefinitions 是加载 BeanDefinition , 但是注意:这里使用了复数 , 说明这里加载的 BeanDefinition 可能会存在多个 。
@Overridepublic int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {return loadBeanDefinitions(new EncodedResource(resource));}复制代码
- 文件系统(02):基于SpringBoot管理Xml和CSV
- SpringBoot2.x入门到项目实战课程系列(第二章)
- SpringBoot集成Mybatis
- 大牛深入解析SpringBoot核心运行原理和运作原理源码
- SpringBoot写后端接口,看这一篇就够了
- 9款游戏13块SSD:测试固态硬盘对游戏加载速度影响有多大?
- Spring Boot 中 @EnableX 注解的驱动逻辑
- SpringBoot2.x入门到项目实战课程系列(第五章)
- SpringBoot整合JWT+Shiro
- 14 个 SpringMVC顶级技巧,随时用随时爽