博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring源码阅读-spring启动
阅读量:5875 次
发布时间:2019-06-19

本文共 5720 字,大约阅读时间需要 19 分钟。

 最近抽空看了下spring源码,我们一起从web容器启动开始,一步一步分析spring是如何被拉起,如何加载加载其配置文件,如何使用加载到容器上下文中的对象

web.xml

web.xml中的spring容器配置

org.springframework.web.context.ContextLoaderListener

 

ContextLoaderListner如何拉起?

  ContextLoaderListener是spring核心功能启动器,该监听器会监听Servlet容器启动事件,一旦监听到该事件就拉起spring整个容器的启动。

  

  • ContextLoaderListener实现了javax.servlet.ServletContextListener接口,该接口的contextInitialized方法用来对扩展的容器进行初始化,ContextLoaderListener在该方法中对spring上下文进行初始化。
  • ContextLoaderListener继承ContextLoader,ContextLoader.initWebApplicationContext方法创建容器Context,并且调度配置文件加载。

            ContextLoader.initWebApplicationContext方法中Context创建代码如下:            

1 if (this.context == null) { 2         this.context = createWebApplicationContext(servletContext); 3     } 4     if (this.context instanceof ConfigurableWebApplicationContext) { 5         ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; 6         if (!cwac.isActive()) { 7             // The context has not yet been refreshed -> provide services such as 8             // setting the parent context, setting the application context id, etc 9             if (cwac.getParent() == null) {10                 // The context instance was injected without an explicit parent ->11                 // determine parent for root web application context, if any.12                 ApplicationContext parent = loadParentContext(servletContext);13                 cwac.setParent(parent);14             }15             configureAndRefreshWebApplicationContext(cwac, servletContext);16         }17     }18     servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

 

             初始化容器时需要判断容器是否已经初始化过,如果没有则创建一个新的spring容器

             容器创建流程如下:

 

                                          

 

 

       ContextLoader会首先从ServletContext中获取配置的容器类(参数名:contextClass)

       如果获取不到则使用ContextLoader同一classPath下的ContextLoader.properties中的配置。

       将org.springframework.web.context.WebApplicationContext对应的值作为容器类并实例化容器作为spring的根容器。ContextLoader.properties配置如下:

       

 

Context创建

创建Context实例,刷新Context。

刷新Context:创建Bean工厂,调用ResourceReader加载Spring的bean配置,将每个bean配置构建成一个BeanDefinition对象存储到Bean工厂,bean配置加载完成后需要给Bean工厂设置一系列postProccessor,执行这些Proccessor,Context在postProccessor处理完成后对所有“非懒加载”的单例bean对象进行实例化。实例化后执行BeanPostProcessor的BeanPostProcessorsBeforeInitialization方法,而后对指定了init方法的实例调用init方法,或者对实现了InitializingBean接口的bean调用afterPropertiesSet方法,初始化方法后执行BeanPostProcessor的applyBeanPostProcessorsAfterInitialization方法。实例化结束后向所有监听器推送ContextRefreshedEvent事件。其中供bean实例使用的BeanPostProcessor是ApplicationListenerDetector,通过该Proccessor,bean可以自定义init方法调用前后执行的动作。init执行前可以通过实现InitializingBean接口,init执行后可以通过实现ApplicationListener接口。

 

 Bean工厂继承关系:

对于bean的具体实例化、初始化、

默认的XmlWebApplicationContext

     XmlWebApplicationContext实例化后被存放到ServletContext中,缓存使用的key为:org.springframework.web.context.WebApplicationContext.ROOT

    在web服务中只要能获取到ServletContext就可以根据WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE获取spring根Context

    XmlWebApplicationContext实例化成功后,ContextLoader会调用configureAndRefreshWebApplicationContext对容器上下文进行配置和初始化

    其中就包括Spring基本属性设置、配置文件加载,解析,对象实例化等动作。Spring容器上下文继承关系如下:

    

   XmlWebApplicationContext的配置文件加载,解析,对象实例化等动作都统一在AbstractApplicationContext.refresh方法中完成

   refresh结束后,容器会发布一个ContextRefreshedEvent事件,供依赖容器启动结束的组件或者第三方定制扩展使用(例如Dubbo,通过监听该事件触发其配置加载后的实例包装动作)。

   具体的刷新核心代码我们看一下:

// Prepare this context for refreshing.            prepareRefresh();            // Tell the subclass to refresh the internal bean factory.            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();            // Prepare the bean factory for use in this context.            prepareBeanFactory(beanFactory);            try {                // Allows post-processing of the bean factory in context subclasses.                postProcessBeanFactory(beanFactory);                // Invoke factory processors registered as beans in the context.                invokeBeanFactoryPostProcessors(beanFactory);                // Register bean processors that intercept bean creation.                registerBeanPostProcessors(beanFactory);                // Initialize message source for this context.                initMessageSource();                // Initialize event multicaster for this context.                initApplicationEventMulticaster();                // Initialize other special beans in specific context subclasses.                onRefresh();                // Check for listener beans and register them.                registerListeners();                // Instantiate all remaining (non-lazy-init) singletons.                finishBeanFactoryInitialization(beanFactory);                // Last step: publish corresponding event.                finishRefresh();            }

  

 

BeanFactory

容器刷新涉及最终要的部件是ApplicationContext辅助类以及beanFactory,ApplicationContext负责spring配置文件的加载和解析,将bean配置解析转换成一个个BeanDefinition并传递给bean工厂,bean工厂调度ApplicationContext辅助类的解析工作,并在解析完成后负责bean对象实例化。

 obtainFreshBeanFactory方法完成工厂创建和刷新,工厂刷新工作内容主要是调度ApplicationContex将bean配置解析转换成一个个BeanDefinition,具体的配置解析和加载工作实现在不同的ApplicationContext实现类,例如xml解析在XmlWebApplicationContext中定义。

 

org.apache.xbean.spring.context.XmlWebApplicationContext中的配置加载如下:

通过调用父类org.springframework.web.context.support.XmlWebApplicationContext的loadBeanDefinitions实际完成加载工作,其实所有ApplicationContext的对应的配置加载实现都在org.springframework.web.context.support包下面:

 

 

 

 

org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver负责加载spring配置文件解析器信息配置

 

扩展NameSpaceHandler

DefaultNamespaceHandlerResolver默认从classpath中META-INF/spring.handler文件中读取配置文件解析器映射关系
spring.handler中的配置如下:

其中配置了配置文件命名空间和NamespaceHandler类的映射关系。

NamespaceHandler中定义了不同类型xml节点的解析器。容器启动过程中XmlWebApplicationContext会通过XmlBeanDefinitionReader读取Spring的配置文件,在解析每一个配置节点时,会从NamespaceHandler中获取对应的解析器进行解析并转换成Spring容器中的实例或者spring配置对象。

 

 

转载于:https://www.cnblogs.com/liwutao/p/8627139.html

你可能感兴趣的文章
Linux下ping命令、traceroute命令、tracert命令的使用
查看>>
js replace,正则截取字符串内容
查看>>
socket
查看>>
Highcharts使用表格数据绘制图表
查看>>
Thinkphp5笔记三:创建基类
查看>>
hdu5373
查看>>
4.单链表的创建和建立
查看>>
Android 好看的搜索界面,大赞Animation
查看>>
查询反模式 - GroupBy、HAVING的理解
查看>>
[转]动态加载javascript
查看>>
【协议】5、gossip 协议
查看>>
基于配置文件的redis的主从复制
查看>>
hasura graphql 角色访问控制
查看>>
springmvc中controller内方法跳转forward?redirect?
查看>>
C#委托,事件理解入门 (译稿)转载
查看>>
容器的end()方法
查看>>
[转] Agile Software Development 敏捷软件开发
查看>>
HDU 1007 Quoit Design (最小点对,模板题)
查看>>
Windows Phone 7 自定义事件
查看>>
Objective-c 网址中带中文解决方法
查看>>