在Spring的入口函数refresh()之中进行的。
- AbstractApplicationContext
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//获得一个新的beanFactory,并进行一些相关的load
- protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
- refreshBeanFactory();//通知子类context刷新内部的BeanFactory
- ConfigurableListableBeanFactory beanFactory = getBeanFactory();
- if (logger.isDebugEnabled()) {
- logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
- }
- return beanFactory;
- }
- AbstractRefreshableApplicationContext
- protected final void refreshBeanFactory() throws BeansException {
- if (hasBeanFactory()) {
- destroyBeans();//销毁当前context管理的所有bean
- closeBeanFactory();//关闭beanFactory
- }
- try {//创建一个新的beanFactory(DefaultListableBeanFactory)
- DefaultListableBeanFactory beanFactory = createBeanFactory();
- beanFactory.setSerializationId(getId());
- customizeBeanFactory(beanFactory);
- loadBeanDefinitions(beanFactory);//加载BeanDefinition
- synchronized (this.beanFactoryMonitor) {
- this.beanFactory = beanFactory;
- }
- }
- //...
- }
- XmlWebApplicationContext
- protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
- // Create a new XmlBeanDefinitionReader for the given BeanFactory.
- //创建一个新的XmlBeanDefinitionReader
- XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
- // Configure the bean definition reader with this context's
- // resource loading environment.
- beanDefinitionReader.setEnvironment(this.getEnvironment());
- beanDefinitionReader.setResourceLoader(this);
- beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
- // Allow a subclass to provide custom initialization of the reader,
- // then proceed with actually loading the bean definitions.
- initBeanDefinitionReader(beanDefinitionReader);
- loadBeanDefinitions(beanDefinitionReader);//接着加载BeanDefinition
- }
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
- String[] configLocations = getConfigLocations();//获得ServletConfig的配置文件位置
- if (configLocations != null) {
- for (String configLocation : configLocations) {
- reader.loadBeanDefinitions(configLocation);//根据位置加载BeanDefinition
- }
- }
- }
- 中间省略
- XmlBeanDefinitionReader
- public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
- BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
- documentReader.setEnvironment(this.getEnvironment());
- int countBefore = getRegistry().getBeanDefinitionCount();
- documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//创建一个ReaderContext,
- //注册BeanDefinition
- return getRegistry().getBeanDefinitionCount() - countBefore;
- }
- protected XmlReaderContext createReaderContext(Resource resource) {
- if (this.namespaceHandlerResolver == null) {//创建默认的名称控件处理器解析器
- this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
- }//返回创建好的xmlReaderContext,将创建好的namespaceHandlerResolver传入
- return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
- this.sourceExtractor, this, this.namespaceHandlerResolver);
- }
- protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {//对应的NamespaceHandlerResolver
- return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader());
- }
- public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
- this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);//这个位置就在META-INF/spring.handlers
- }
- 接着往下走注册BeanDefinitioni的过程
- DefaultBeanDefinitionDocumentReader
- public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
- this.readerContext = readerContext;
- logger.debug("Loading bean definitions");
- Element root = doc.getDocumentElement();
- doRegisterBeanDefinitions(root);//注册beanDefinition 将root根节点传入
- }
- protected void doRegisterBeanDefinitions(Element root) {
- //....
- this.delegate = createDelegate(this.readerContext, root, parent);//创建一个委托
- preProcessXml(root);
- parseBeanDefinitions(root, this.delegate);//处理
- postProcessXml(root);
- this.delegate = parent;
- }
- protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
- if (delegate.isDefaultNamespace(root)) {
- NodeList nl = root.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) {
- Node node = nl.item(i);
- if (node instanceof Element) {
- Element ele = (Element) node;
- if (delegate.isDefaultNamespace(ele)) {
- parseDefaultElement(ele, delegate);
- }
- else {
- delegate.parseCustomElement(ele);//解析自定义的节点
- }
- }
- }
- }
- else {
- delegate.parseCustomElement(root);
- }
- }
- public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {//null
- String namespaceUri = getNamespaceURI(ele);//根据之前设置的解析器对这个uri进行解析,获得一个NamespaceHandler
- //通过键值对的形式存在文件里面,在resolve里面对类名获取,然后实例化一个handler对象
- NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
- //....现在可以对配置文件进行解析了。
- return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
- }
- DefaultNamespaceHandlerResolver
- public NamespaceHandler resolve(String namespaceUri) {
- Map<String, Object> handlerMappings = getHandlerMappings();
- Object handlerOrClassName = handlerMappings.get(namespaceUri);//获取处理器的类名
- if (handlerOrClassName == null) {
- return null;
- }
- else if (handlerOrClassName instanceof NamespaceHandler) {
- return (NamespaceHandler) handlerOrClassName;
- }
- else {
- String className = (String) handlerOrClassName;
- try {//利用反射根据类名进行类的装载
- Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
- if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
- throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
- "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
- }//根据类进行实例化
- NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
- namespaceHandler.init();
- handlerMappings.put(namespaceUri, namespaceHandler);//缓存这个handler,下次其他的可以再次利用
- return namespaceHandler;
- }
- //....
- }
- }
Spring通过在META-INF/spring.handlers中的属性进行配置文件解析的更多相关文章
-
【Spring源码解读】bean标签中的属性
说明 今天在阅读Spring源码的时候,发现在加载xml中的bean时,解析了很多标签,其中有常用的如:scope.autowire.lazy-init.init-method.destroy-met ...
-
【Spring源码解读】bean标签中的属性(二)你可能还不够了解的 abstract 属性和 parent 属性
abstract 属性说明 abstract 在java的语义里是代表抽象的意思,用来说明被修饰的类是抽象类.在Spring中bean标签里的 abstract 的含义其实也差不多,表示当前bean是 ...
-
SSM-SpringMVC-10:SpringMVC中PropertiesMethodNameResolver属性方法名称解析器
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 上次的以继承MultiActionController可以实现一个处理器中多个处理方法,但是局限出来了,他们的 ...
-
【Spring源码解读】bean标签中的属性(一)你可能还不够了解的 scope 属性
scope 属性说明 在spring中,在xml中定义bean时,scope属性是用来声明bean的作用域的.对于这个属性,你也许已经很熟悉了,singleton和prototype信手捏来,甚至还能 ...
-
Spring Boot2 系列教程(九)Spring Boot 整合 Thymeleaf
虽然现在慢慢在流行前后端分离开发,但是据松哥所了解到的,还是有一些公司在做前后端不分的开发,而在前后端不分的开发中,我们就会需要后端页面模板(实际上,即使前后端分离,也会在一些场景下需要使用页面模板, ...
-
iOS中WebKit框架应用与解析
WebKit是iOS8之后引入的专门负责处理网页视图的框架,其比UIWebView更加强大,性能也更优. 引言 在iOS8之前,在应用中嵌入网页通常需要使用UIWebView这样一个类,这个类通过UR ...
-
【spring源码学习】spring的IOC容器之自定义xml配置标签扩展namspaceHandler向IOC容器中注册bean
[spring以及第三方jar的案例]在spring中的aop相关配置的标签,线程池相关配置的标签,都是基于该种方式实现的.包括dubbo的配置标签都是基于该方式实现的.[一]原理 ===>sp ...
-
Spring中AOP相关源码解析
前言 在Spring中AOP是我们使用的非常频繁的一个特性.通过AOP我们可以补足一些面向对象编程中不足或难以实现的部分. AOP 前置理论 首先在学习源码之前我们需要了解关于AOP的相关概念如切点切 ...
-
spring第一课,beans配置(中)——自动装配
•Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 <bean> 的 autowire 属性里指定自动装配的模式 •byType(根据类型自动装配): 若 IOC 容器 ...
随机推荐
-
设计模式的PHP实现示例(转)
symfony2 很多设计模式思想,下面的资料会有点帮助:http://www.open-open.com/lib/view/open1414996676559.html 阅读目录 Creationa ...
-
修改VISUAL STUDIO EXPRESS 2012新建C++文件编码
本站文章除注明转载外,均为本站原创或者翻译. 本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商: 本站部分原创和翻译文章提供markdown格式源码,欢迎使 ...
-
hdu 4122 Alice&#39;s mooncake shop(单调队列)
题目链接:hdu 4122 Alice's mooncake shop 题意: 有n个订单和可以在m小时内制作月饼 接下来是n个订单的信息:需要在mon月,d日,year年,h小时交付订单r个月饼 接 ...
-
iOS错误之-Presenting view controllers on detached view controllers is discouraged
遇到这个警告后找了一下网络资源,基本上只说通过 [self.view.window.rootViewController presentViewController:controller animat ...
-
虚拟机安装tools for Ubuntu
1.启动虚拟机,进入虚拟机 2.选定菜单中的虚拟机按钮,点击安装VMware Tools 3.此时虚拟机上会弹出一些文件, 复制VMwareTools-XXX-XX.tar.gz到桌面,鼠标右键可 ...
-
vs2015编译caffe
有些时候,需要在python3的环境下import caffe,需要用vs2015在python3的环境下,编译pycaffe. microsoft的windows版本的caffe,依赖的库Nuget ...
-
JSON库的使用研究(一)
最近用到JSON,收集了一些资料,整理如下: 选择一个合适的JSON库要从多个方面进行考虑: 字符串解析成JSON性能 字符串解析成Java Object性能 Java Object转JSON性能 集 ...
-
kafka_2.11-2.0.0_常用操作
参考博文:Kafka消费组(consumer group) 参考博文:kafka 1.0 中文文档(九):操作 参考博文:kafka集群管理工具kafka-manager部署安装 以下操作可以在min ...
-
基于vs2015的rdlc报表运行环境部署
先说明一下,rdlc报表是由visual studio来支持的,不是FM. 本次项目采用的是vs2015开发的,当中使用了ReportViewer报表. 两种方式可以支持开发rdlc报表环境: 1)在 ...
-
hdu1599 find the mincost route
题目链接 floyd找最小环 很好理解 #include<algorithm> #include<iostream> #include<cstdlib> #incl ...