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 , 再调用反射生成对象的实例
文章插图
看到这些红框中的内容 , 是不是感觉到非常熟悉 , 这不就是我们在 applicationContext.xml 中定义的一个个标签么?原来这些东西都被 DefaultBeanDefinitionDocumentReader 写死在代码中了 。
文章插图
接下来我们回到 registerBeanDefinitions 这个方法的实现 。
文章插图
我们已经知道 createBeanDefinitionDocumentReader 是通过反射的方式生成了一个 BeanDefinitionDocumentReader 对象 。 下面我们看看方法的第二行做了什么事情 。
getRegistry().getBeanDefinitionCount(); 先看看 getRegistry() 这个方法 。 这个方法基本上都不用考虑 , 肯定是获取到了我们传入进来的 defaultListableBeanFactory 对象 。
private final BeanDefinitionRegistry registry;@Overridepublic final BeanDefinitionRegistry getRegistry() {return this.registry;}复制代码
返回了成员变量 registry , 那么这个 registry 在哪里赋值的呢?看看我们在示例代码中的第三步 new XMLBeanDefinitionReader() 中就知道了 , 在该类的构造方法中 , 我们赋值了 registry 这个成员变量的值 。文章插图
接着看看 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 的定义 。看看具体实现
- 文件系统(02):基于SpringBoot管理Xml和CSV
- SpringBoot2.x入门到项目实战课程系列(第二章)
- SpringBoot集成Mybatis
- 大牛深入解析SpringBoot核心运行原理和运作原理源码
- SpringBoot写后端接口,看这一篇就够了
- 9款游戏13块SSD:测试固态硬盘对游戏加载速度影响有多大?
- Spring Boot 中 @EnableX 注解的驱动逻辑
- SpringBoot2.x入门到项目实战课程系列(第五章)
- SpringBoot整合JWT+Shiro
- 14 个 SpringMVC顶级技巧,随时用随时爽