IOC容器的定位,载入 ,注册
2020-08-19 10:48:17 10 举报
登录查看完整内容
IOC源码追踪
作者其他创作
大纲/内容
old? 还记得 “允许 bean 覆盖” 这个配置吗?allowBeanDefinitionOverriding
而对于其他的标签,将进入到 delegate.parseCustomElement(element) 这个分支。如我们经常会使用到的 <mvc />、<task />、<context />、<aop />等。
容器启动前做好准备工作
// 这块说的是根节点 <beans ... profile=\"dev\" /> 中的 profile 是否是当前环境需要的,// 如果当前环境配置的 profile 不包含此 profile,那就直接 return 了,不对此 <beans /> 解析
将 BeanDefinition 放到这个 map 中,这个 map 保存了所有的 BeanDefinition
这一步主要将解析配置文件,并提取配置文件中的信息,将提取的信息映射到BeanDefinition中,注册到容器的map中去。(bean没有在这里实例化)
容器中不存在重名的情况
将 name 属性的定义按照 “逗号、分号、空格” 切分,形成一个 别名列表数组,
获取子标签
关闭旧的容器,创建新的容器,并且解析xml,载入并注册bean
接下来是最重要的 loadBeanDefinitions(beanFactory) 方法了,这个方法将根据配置,加载各个 Bean,然后放到 BeanFactory 中。读取配置的操作在 XmlBeanDefinitionReader 中,其负责加载配置、解析。
将 <bean /> 节点中的信息提取出来,然后封装到一个 BeanDefinitionHolder 中
整个bean解析完成后得到一个beandefinition
加锁防止其他线程再次启动容器
将原来的bean覆盖掉
不允许重名抛出异常
把 beanClassName 设置为 Bean 的别名
钩子
解析 default namespace 下面的几个元素
从xml根节点开始解析
加载和解析配置文件
遍历子标签
从这里开始向容器中注册BeanDefinition
这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字
经过漫长的链路,一个配置文件终于转换为一颗 DOM 树了,注意,这里指的是其中一个配置文件,不是所有的,读者可以看到上面有个 for 循环的。
BeanDefinitionReaderUtils
对几个默认标签进行解析
DefaultListableBeanFactory
// 如果我们不定义 id 和 name,那么我们引言里的那个例子:// 1. beanName 为:com.javadoop.example.MessageServiceImpl#0 // 2. beanClassName 为:com.javadoop.example.MessageServiceImpl
// 判断是否已经有其他的 Bean 开始初始化了.// 注意,\"注册Bean\" 这个动作结束,Bean 依然还没有初始化,我们后面会有大篇幅说初始化过程,// 在 Spring 容器启动的最后,会预初始化所有的 singleton beans
customizeBeanFactory(beanFactory) 比较简单,就是配置是否允许 BeanDefinition 覆盖、是否允许循环引用。‘1.BeanDefinition 的覆盖问题可能会有开发者碰到这个坑,就是在配置文件中定义 bean 时使用了相同的 id 或 name,默认情况下,allowBeanDefinitionOverriding 属性为 null,如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖。2.循环引用也很好理解:A 依赖 B,而 B 依赖 A。或 A 依赖 B,B 依赖 C,而 C 依赖 A。默认情况下,Spring 允许循环依赖。
// 返回值:返回从当前配置文件加载了多少数量的 Bean
根据配置创建 BeanDefinition 实例
一个 <bean /> 标签产生了一个 BeanDefinitionHolder 的实例
这里是beans中含beans存在递归调用
解析其他 namespace 的元素
loadBeanDefinitions(resources);
// default namespace 涉及到的就四个标签 <import />、<alias />、<bean /> 和 <beans />,// 其他的属于 custom 的
存在重名的情况
doRegisterBeanDefinitions(ele);
BeanDefinitionParserDelegate 必定是一个重要的类,它负责解析 Bean 定义
这里的四个标签之所以是 default 的,是因为它们是处于这个 namespace 下定义的:http://www.springframework.org/schema/beans又到初学者科普时间,不熟悉 namespace 的读者请看下面贴出来的 xml,这里的第二行 xmlns 就是咯。<beans xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.springframework.org/schema/beans\" xsi:schemaLocation=\" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\" default-autowire=\"byName\">而对于其他的标签,将进入到 delegate.parseCustomElement(element) 这个分支。如我们经常会使用到的 <mvc />、<task />、<context />、<aop />等。这些属于扩展,如果需要使用上面这些 ”非 default“ 标签,那么上面的 xml 头部的地方也要引入相应的 namespace 和 .xsd 文件的路径,如下所示。同时代码中需要提供相应的 parser 来解析,如 MvcNamespaceHandler、TaskNamespaceHandler、ContextNamespaceHandler、AopNamespaceHandler 等。假如读者想分析 <context:property-placeholder location=\"classpath:xx.properties\" /> 的实现原理,就应该到 ContextNamespaceHandler 中找答案。<beans xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.springframework.org/schema/beans\" xmlns:context=\"http://www.springframework.org/schema/context\" xmlns:mvc=\"http://www.springframework.org/schema/mvc\" xsi:schemaLocation=\" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd \" default-autowire=\"byName\">
0 条评论
回复 删除
下一页