Spring Bean加载流程分析(通过 XML 方式加载)( 五 )


接下来看看 doLoadBeanDefinitions 的具体实现
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {Document doc = doLoadDocument(inputSource, resource);int count = registerBeanDefinitions(doc, resource);return count;}// ... 省略部分代码}复制代码显然 doLoadBeanDefinitions 做了两件事情

  • 从给定的 Resource 资源中读取 XML 文件中的内容 , 该方法返回了一个 Document 对象
  • 通过 Document 对象和给定的 Resource 资源中注册 bean 的定义
对于 doLoadDocument 方法的读取 , 实际上就是读取 XML 里面的内容 , 并返回一个 Document 对象 。 这部分就不跟源码进去看了 , 有兴趣可以自己搜索一下 XML 解析相关的内容 。
下面看看 registerBeanDefinitions 相关的源码 , 看看是如何从 document 中获取到注册到 bean 的定义的 。
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {// 创建了一个 Bean 定义文档读取器BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();// 获取到工厂中已经获取到 Bean 定义的数量int countBefore = getRegistry().getBeanDefinitionCount();// 注册 Bean 定义documentReader.registerBeanDefinitions(doc, createReaderContext(resource));// 返回本次要注册 bean 定义的数量return getRegistry().getBeanDefinitionCount() - countBefore;}复制代码看看如何获取一个 Bean 定义文档读取器(BeanDefinitionDocumentReader)
private Class documentReaderClass =DefaultBeanDefinitionDocumentReader.class;protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {return BeanUtils.instantiateClass(this.documentReaderClass);}复制代码这里看到了调用了 Spring 自身提供的一个 BeanUtils.instantiateClass 方法 。 传入了 DefaultBeanDefinitionDocumentReader 的 class 文件 , 稍加思考我们便可以知道该方法是通过反射的方式生成了 BeanDefinitionDocumentReader 这个对象的实例 。 下面去 BeanUtils.instantiateClass 源码验证一下 。
public staticT instantiateClass(Class clazz) throws BeanInstantiationException {Assert.notNull(clazz, "Class must not be null");// 如果传入的是一个接口 , 则抛异常if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {// 实例化类 , 获取构造器return instantiateClass(clazz.getDeclaredConstructor());}catch (NoSuchMethodException ex) {// 对 Kotlin 的支持Constructor ctor = findPrimaryConstructor(clazz);if (ctor != null) {return instantiateClass(ctor);}throw new BeanInstantiationException(clazz, "No default constructor found", ex);}catch (LinkageError err) {throw new BeanInstantiationException(clazz, "Unresolvable class definition", err);}}复制代码看看重载的 instantiateClass 方法 , 一目了然 , 全部都是反射相关的内容 。
public staticT instantiateClass(Constructor ctor, Object... args) throws BeanInstantiationException {Assert.notNull(ctor, "Constructor must not be null");try {// 设置 makeAccessible 属性为 true ,ReflectionUtils.makeAccessible(ctor);if (KotlinDetector.isKotlinReflectPresent()}else {Class