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

[] parameterTypes = ctor.getParameterTypes();Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");Object[] argsWithDefaultValues = new Object[args.length];for (int i = 0 ; i < args.length; i++) {if (args[i] == null) {Class parameterType = parameterTypes[i];argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);}else {argsWithDefaultValues[i] = args[i];}}return ctor.newInstance(argsWithDefaultValues);}}// ... 省略部分代码}复制代码注意在该方法的头部调用了 ReflectionUtils.makeAccessible(ctor); 方法 , 该方法即表明了即使你提供了私有的构造方法 , Spring 也能帮你将对象创建出来(反射的内容) , 看到最后的 return , 很明显 BeanUtils.instantiateClass 就是通过反射的方式生成了对象 。

  • 如果没有提供构造方法 , 则采用默认的构造方法
  • 如果提供了私有的构造方法 , 则设置 accessible 属性为 true , 再调用反射生成对象的实例
通过以上的方式可以看出 , Spring 是想尽了一切办法在帮我们正常创建一个对象 。看看传入的 DefaultBeanDefinitionDocumentReader 的声明
Spring Bean加载流程分析(通过 XML 方式加载)文章插图
看到这些红框中的内容 , 是不是感觉到非常熟悉 , 这不就是我们在 applicationContext.xml 中定义的一个个标签么?原来这些东西都被 DefaultBeanDefinitionDocumentReader 写死在代码中了 。
Spring Bean加载流程分析(通过 XML 方式加载)文章插图
接下来我们回到 registerBeanDefinitions 这个方法的实现 。
Spring Bean加载流程分析(通过 XML 方式加载)文章插图
我们已经知道 createBeanDefinitionDocumentReader 是通过反射的方式生成了一个 BeanDefinitionDocumentReader 对象 。 下面我们看看方法的第二行做了什么事情 。
getRegistry().getBeanDefinitionCount(); 先看看 getRegistry() 这个方法 。 这个方法基本上都不用考虑 , 肯定是获取到了我们传入进来的 defaultListableBeanFactory 对象 。
private final BeanDefinitionRegistry registry;@Overridepublic final BeanDefinitionRegistry getRegistry() {return this.registry;}复制代码返回了成员变量 registry , 那么这个 registry 在哪里赋值的呢?看看我们在示例代码中的第三步 new XMLBeanDefinitionReader() 中就知道了 , 在该类的构造方法中 , 我们赋值了 registry 这个成员变量的值 。
Spring Bean加载流程分析(通过 XML 方式加载)文章插图
接着看看 getBeanDefinitionCount 的实现
/** Map of bean definition objects, keyed by bean name. */private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);@Overridepublic int getBeanDefinitionCount() {return this.beanDefinitionMap.size();}复制代码就是返回了 beanDefinitionMap 这个 concurrentHashMap 的大小 。 该变量的定义为 Map 类型 , 是一个以 bean 名称为 key , BeanDefinition 为 value 的 Map 对象 。
结合上面的分析 , 那么 int countBefore = getRegistry().getBeanDefinitionCount(); 返回的实际上是未加载之前的 BeanDefinition 的数量 。
接着看 registerBeanDefinitions 的第三行实现 。 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 通过文档读取器开始从文档中注册 bean 的定义 。看看具体实现


推荐阅读