- 浏览: 60648 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
liwanfeng:
看楼上的评价不错,但是格式可能是je改版,现在看格式比较乱啊! ...
Spring DispatcherServlet MVC 源码分析(Webapplicationcontext的生成) -
pian_yun:
我的理解是,没事实例化的function xxx(){}里面的 ...
Javascript的关于this用法的一个问题的分析 -
yxgd:
...
Spring ProxyFactoryBean是如何代理Class分析 -
charles_zuo:
讲解的很详细,按照LZ的分析看了下源码,条理很清晰,谢谢
Spring DispatcherServlet MVC 源码分析(Webapplicationcontext的生成) -
sorphi:
再贴一篇,关于是否能自动判断post方式提交过来的数据编码
...
Servlet 乱码问题
BeanFactory的初始化的触发——><o:p></o:p>
FrameworkServlet中的wac.refresh()<o:p></o:p>
<o:p> </o:p>
如下为初始化MVC部分的操作:<o:p></o:p>
- initmultipartresolver();
- initlocaleresolver();
- initthemeresolver();
- inithandlermappings();
- inithandleradapters();
- inithandlerexceptionresolvers();
- initviewresolver();
<o:p></o:p>
<o:p> </o:p>
现在有一个疑问 initHandlerMappings(ApplicationContext context)中的ApplicationContext的实现在web中是哪一个,可以从下面得到结论<o:p></o:p>
<o:p> </o:p>
- public static final Class DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
- private Class contextClass = DEFAULT_CONTEXT_CLASS;
<o:p></o:p>
<o:p> </o:p>
可以看出这个地方是实例化的是XmlWebApplicationContext的一个实例,那么这个实例是在哪个地方被实例化的呢?在DispatchServelet的父类FrameworkServlet中可以找到如下的代码,<o:p></o:p>
<o:p> </o:p>
- WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
- WebApplicationContext wac = createWebApplicationContext(parent);
<o:p></o:p>
<o:p> </o:p>
ok,我们现在就可以用这个wac了,顺便看看这个实例里边都有什么东西:<o:p></o:p>
<o:p> </o:p>
- wac.setParent(parent);//web.xml中加载的context
- wac.setServletContext(getServletContext());
- wac.setServletConfig(getServletConfig());
- wac.setNamespace(getNamespace());
- if (getContextConfigLocation() != null) {
- wac.setConfigLocations(
- StringUtils.tokenizeToStringArray(
- getContextConfigLocation(), ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
- }//比较有用
- wac.addApplicationListener(this);
<o:p></o:p>
<o:p> </o:p>
继续我们的MVC探索--><o:p></o:p>
下面是MVC的部分,提前分析一下<o:p></o:p>
- protected List getDefaultStrategies(ApplicationContext context, Class strategyInterface) throws BeansException {
- String key = strategyInterface.getName();//equals org.springframework.web.servlet.HandlerMapping
- List strategies = null;
- String value = defaultStrategies.getProperty(key);
- //org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping.class
- if (value != null) {
- String[] classNames = StringUtils.commaDelimitedListToStringArray(value);//等效于split
- strategies = new ArrayList(classNames.length);
- for (int i = 0; i < classNames.length; i++) {
- String className = classNames[i];
- try {
- Class clazz = ClassUtils.forName(className, getClass().getClassLoader());
- Object strategy = createDefaultStrategy(context, clazz);
- strategies.add(strategy);
- }
- catch (ClassNotFoundException ex) {
- throw new BeanInitializationException(
- "Could not find DispatcherServlet's default strategy class [" + className +
- "] for interface [" + key + "]", ex);
- }
- catch (LinkageError err) {
- throw new BeanInitializationException(
- "Error loading DispatcherServlet's default strategy class [" + className +
- "] for interface [" + key + "]: problem with class file or dependent class", err);
- }
- }
- }else {
- strategies = Collections.EMPTY_LIST;
- }
- return strategies;
- }
- protected Object createDefaultStrategy(ApplicationContext context, Class clazz) throws BeansException {
- return context.getAutowireCapableBeanFactory().createBean(
- clazz, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
- //org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping.class
- }
<o:p></o:p>
context 为XmlWebApplicationContext的一个实例,而<o:p></o:p>
<o:p> </o:p>
- public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext
- public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableApplicationContext
- implements ConfigurableWebApplicationContext, ThemeSource
- public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext
- public abstract class AbstractApplicationContext extends DefaultResourceLoader
- implements ConfigurableApplicationContext, DisposableBean {
- public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
- return getBeanFactory();
- }
- }
- 在AbstractRefreshableApplicationContext中
- public final ConfigurableListableBeanFactory getBeanFactory() {
- synchronized (this.beanFactoryMonitor) {
- if (this.beanFactory == null) {
- throw new IllegalStateException("BeanFactory not initialized or already closed - " +
- "call 'refresh' before accessing beans via the ApplicationContext");
- }
- return this.beanFactory;
- }
- }
<o:p>
说明这个时候BeanFactory已经初始化好了,那么在哪个地方初始化好的呢?可以想象到的地方就是XmlWebApplicationContext在new的时候会初始化这个BeanFactory?在WebApplicationContext createWebApplicationContext(WebApplicationContext parent)时候,也就是在初始化ApplicationContext的时候有如下操作<o:p></o:p>
<o:p> </o:p>
wac.refresh();<o:p></o:p>
<o:p> </o:p>
也就是初始化ApplicationContext之后会马上初始化BeanFacory<o:p></o:p>
从类结构里我们能找到这个方法来自它的父类: AbstractApplicationContext 在它的 refresh() 方法内我们可以看到 spring 的复杂逻辑。首先执行了refreshBeanFactory(); (来自 AbstractRefreshableApplicationContext )见 (a),<o:p></o:p>
<o:p> </o:p>
(a)refreshBeanFactory(); 这个方法由负责维护变量 beanFactory 的子类AbstractRefreshableApplicationContext 实现,默认情况下<o:p></o:p>
这个方法直接实例化一个新的 DefaultListableBeanFactory 类型的 BeanFacorty, <o:p></o:p>
- protected final void refreshBeanFactory() throws BeansException {
- DefaultListableBeanFactory beanFactory = createBeanFactory();
- customizeBeanFactory(beanFactory);
- loadBeanDefinitions(beanFactory);
- }
- protected DefaultListableBeanFactory createBeanFactory() {
- return new DefaultListableBeanFactory(getInternalParentBeanFactory());
- }
- AbstractApplicationContext.java
- protected BeanFactory getInternalParentBeanFactory() {//判断用的是ApplicationContext or BeanFactory
- return (getParent() instanceof ConfigurableApplicationContext) ?
- ((ConfigurableApplicationContext) getParent()).getBeanFactory() : (BeanFactory) getParent();
- }
- public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
- implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {}
- XmlWebApplicationContext.java-->
- /**
- * Loads the bean definitions via an XmlBeanDefinitionReader.
- * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
- * @see #initBeanDefinitionReader
- * @see #loadBeanDefinitions
- */
- protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
- // Create a new XmlBeanDefinitionReader for the given BeanFactory.
- XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
- // Configure the bean definition reader with this context's
- // resource loading environment.
- 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);
- }
- public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
- }
- XmlBeanDefinitionReader 继承了 AbstractBeanDefinitionReader,AbstractBeanDefinitionReader的构造函数如下:
- protected AbstractBeanDefinitionReader(BeanDefinitionRegistry beanFactory) {//DefaultListableBeanFactory实现了
- //BeanDefinitionRegistry
- Assert.notNull(beanFactory, "Bean factory must not be null");
- this.beanFactory = beanFactory;
- // Determine ResourceLoader to use.如果beanFactory不但实现了BeanDefinitionRegistry,而且实现了ResourceLoader
- //通常的这样的情况是实现了org.springframework.context.ApplicationContext的BeanFactory,这一点可以查看(c)部分
- if (this.beanFactory instanceof ResourceLoader) {
- this.resourceLoader = (ResourceLoader) this.beanFactory;
- }else {
- this.resourceLoader = new PathMatchingResourcePatternResolver();
- }
- }
<o:p></o:p>
初始化完了AbstractBeanDefinitionReader之后,继续XmlBeanDefinitionReaderd的初始化:<o:p></o:p>
- public XmlBeanDefinitionReader(BeanDefinitionRegistry beanFactory) {
- if (getResourceLoader() != null) {//getResourceLoader已经得到
- this.entityResolver = new ResourceEntityResolver(getResourceLoader());
- //entityResolver
- }else {
- this.entityResolver = new DelegatingEntityResolver(ClassUtils.getDefaultClassLoader());
- }
- }
<o:p></o:p>
上面的初始化相当于初始化了 XmlBeanDefinitionReader的resourceLoader和entityResolver<o:p></o:p>
然后就是对各个配置路径的初始化工作:<o:p></o:p>
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
- String[] configLocations = getConfigLocations();
- if (configLocations != null) {
- for (int i = 0; i < configLocations.length; i++) {
- reader.loadBeanDefinitions(configLocations[i]);
- }
- }
- }
<o:p></o:p>
XmlBeanDefinitionReader中的初始化工作,因此所有的xml的解析实际上是在这个类文件中完成的 <o:p></o:p>
- public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
- InputStream inputStream = encodedResource.getResource().getInputStream();
- try {
- InputSource inputSource = new InputSource(inputStream);
- if (encodedResource.getEncoding() != null) {
- inputSource.setEncoding(encodedResource.getEncoding());
- }
- return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
- }
- finally{
- inputStream.close();
- }
- }catch (IOException ex) {
- throw new BeanDefinitionStoreException(
- "IOException parsing XML document from " + encodedResource.getResource(), ex);
- }
- }
- protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
- throws BeanDefinitionStoreException {
- int validationMode = getValidationModeForResource(resource);
- Document doc = this.documentLoader.loadDocument(//获得解析的dom路径
- inputSource, this.entityResolver, this.errorHandler, validationMode, this.namespaceAware);
- return registerBeanDefinitions(doc, resource);
- }
- (c)
- public abstract class AbstractApplicationContext extends DefaultResourceLoader
- implements ConfigurableApplicationContext, DisposableBean{};//AbstractApplicationContext继承了DefaultResourceLoader
- public class DefaultResourceLoader implements ResourceLoader{}//DefaultResourceLoader实现了ResourceLoader
- public DefaultResourceLoader() {//构造函数
- this.classLoader = ClassUtils.getDefaultClassLoader();
- }
- public static ClassLoader getDefaultClassLoader() {
- cl = Thread.currentThread().getContextClassLoader();//取得Application级的ClassLoader
- }
<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
然后调用一个起缓冲作用的配置函数生成一个将 beanFacroty 包装起来的对象 beanDefinitionReader ,然后对这个对象进行属性配置,实际上该方法主要负责生成一个临时的操作对象,对应调用的函数为“loadBeanDefinitions(beanFactory);”该方法为初始化期间较为重要的一个。该方法来自其子类:AbstractRefreshableWebApplicationContext <o:p></o:p>
<o:p>
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
- String[] configLocations = getConfigLocations();// xml文件的配置的路径
- if (configLocations != null) {
- for (int i = 0; i < configLocations.length; i++) {
- reader.loadBeanDefinitions(configLocations[i]);
- }
- }
- }
<o:p>
对应的函数:<o:p></o:p>
protected void loadBeanDefinitions(DefaultListableBeanFactory) ,然后这里又调用了自己定义的 <o:p></o:p>
protected void loadBeanDefinitions(XmlBeanDefinitionReader) 方法。此时,它就使用到了在以前中设置了的( wac.setConfigLocations(……)) 我们开发中密切相关的配置文件。(同时也要记住此时这个函数的参数 beanDefinitionReader ,之前已经设置了”beanDefinitionReader.setResourceLoader(this) “这里的 this 是我们在前面见到的 XmlWebApplicationContext (一个定义好了的上下文))。接着往下:reader.loadBeanDefinitions(configLocations[i]); reader 开始加载我们配置文件内的东西了,不过真正复杂的实现此时才开始,我们继续往下走,在接下来的方法内默认情况下会执行:if (resourceLoader instanceof ResourcePatternResolver)(该判断条件为true ),由于从上面我们知道: beanDefinitionReader.setResourceLoader(this); 而 this 的类型为: XmlWebApplicationContext所以 ((ResourcePatternResolver) resourceLoader).getResources(location); 得到一个 Resource[] 数组,接下来调用:int loadCount = loadBeanDefinitions(resources); 该函数继续调用自己子类定义的一系列临时接口最终执行到 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 在这个函数内初始化了处理 xml 文件的一些对象并将用户的配置文件解析为一个 Document 对象。然后又执行了一系列函数直到return parser.registerBeanDefinitions(this, doc, resource); 这个函数来自我们新建的 DefaultXmlBeanDefinitionParser,在这个类里最终执行了对 xml 文件的解析工作和对 beanFacroty 变量执行了设置工作。<o:p></o:p>
<o:p> </o:p>
(b)终于我们从这些繁杂的逻辑中跳了出来,继续执行 AbstractApplicationContext.refresh() 下面的工作,后续的代码主要仍旧是往一些常量里面设值。<o:p></o:p>
<o:p> </o:p>
此时 Spring BeanFactory初始化过程就结束了。发表评论
-
Spring DispatcherServlet MVC 源码分析(Webapplicationcontext的生成)
2007-08-25 09:26 3951<servlet></servlet> ... -
Spring 源码分析(Log4jConfigListener Parts)
2007-08-25 09:21 5037java 代码 Spring O ... -
Spring Open Sourse Research(ContextLoaderListener Parts)
2007-08-25 09:21 2955Spring 源码分析(ContextLoaderListe ... -
Spring ProxyFactoryBean是如何代理Class分析
2007-08-25 09:19 40141、ProxyFactoryBean 把proxy的创建交给A ...
相关推荐
Spring源码学习九:DispatcherServlet初始化源码分析1
弃用了struts,用spring mvc框架做了几个项目,感觉都不错,而且使用了注解方式,可以省掉一大堆配置文件。本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mvc和rest小例子没有介绍到数据层的内容,...
Spring MVC 教程 快速入门 深入分析 目录 一、前言 二、spring mvc 核心类与接口 三、spring mvc 核心流程图 四、spring mvc DispatcherServlet说明 五、spring mvc 双亲上下文的说明 六、springMVC-mvc.xml 配置...
包括:功能、配置、上下文关系、初始化顺序等 第三章:注解式控制器开发详解 包括:注解式开发HelloWorld、处理器定义、请求映射、REST风格支持、请求数据映射、数据绑定等诸多内容 第四章:数据类型转换 包括:...
四、spring mvc DispatcherServlet说明 五、spring mvc 双亲上下文的说明 六、springMVC-mvc.xml 配置文件片段讲解 七、spring mvc 如何访问到静态的文件,如jpg,js,css? 八、spring mvc 请求如何映射到具体的...
这个jar文件包含Spring MVC框架相关的所有类。 包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、XSLT相关类。 当然,如果你的应用使用了独立的MVC框架,则无需这个JAR文件里的...
DispatcherServlet 是Spring MVC 的入口 所有进入Spring Web 的 Request 都经过 DispatcherServlet 需要在 web.xml 中注册 DispatcherServlet <servlet> <servlet-name>dispatherContext</servlet-name> ...
四、spring mvc DispatcherServlet说明 五、spring mvc 双亲上下文的说明 六、springMVC-mvc.xml 配置文件片段讲解 七、spring mvc 如何访问到静态的文件,如jpg,js,css? 八、spring mvc 请求如何映射到具体的...
首先, 我需要在你心里建立起 Spring MVC 的基本概念. 基于 Spring 的 Web 应用程序接收到 http://localhost:8080/hello.do(事实上请求路径是 /hello.do) 的请求后, Spring 将这个请求交给一个名为 helloController ...
spring mvc DispatcherServlet说明 spring mvc 双亲上下文的说明 springMVC-mvc.xml 配置文件片段讲解 spring mvc 如何访问到静态的文件,如jpg,js,css? spring mvc 处理ajax请求 spring mvc 转发与重定向 如何给...
spring-mvc与xfire的集成 对于这样的集成,看看里面的配置文件就行了 一个简单的接口,对应一个简单的实现。 然后在配置文件里指明就可以了。 DispatcherServlet本身会管理xfire的请求 配置文件中配置的key可以理解...
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发...
Spring Portlet MVC和其Web MVC可以说是如出一辙,只是在Web MVC中处于核心的DispatcherServlet在Portlet MVC中换成了DispatcherPortlet
总结:首先,SpringMVC框架在启动的时候会遍历Spring容器中的所有bean,对标注了@Controller或并,使用@RequestMapping注解
What you'll learn Key Spring Framework fundamentals How to use the Spring MVC architecture How to develop with the DispatcherServlet How to write Controllers How to work with Resolving and ...
DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。 具体请参考第二章的图2-1。 ...
Spring3 MVC结构核心流程全解 全部jar包都是自己一个个找出来的 使用Spring MVC,配置DispatcherServlet
本文通过分析Spring MVC的核心组件和执行流程,提供了一个全面的学习指南。 Spring MVC基于Model-View-Controller(MVC)架构模式,优化了Web应用程序的设计和开发。在Spring MVC中,DispatcherServlet作为前端控制...
我自己写的Spring MVC的一个HelloWold,从建HelloWorld工程,搭建环境Install spring,配置web.xml,配置SpringMVC的配置文件springDispatcherServlet-servlet.xml,添加控制器类,建jsp页面,部署 Tomcat,最后运行...
中文名: 精通Spring MVC 原名: Pro Spring MVC With Web Flow 作者: Deinum Serneels Yates Ladd Vanfleteren图书分类: 软件 资源格式: PDF 版本: 英文版 出版社: Apress书号: 978-1-4302-4155-3发行时间: 2012年 ...