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 的继承图 。
Spring Bean加载流程分析(通过 XML 方式加载)文章插图
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));}复制代码


推荐阅读