`

MVC架构探究及其源码实现(3)-WebApplicationContext

 
阅读更多

直接利用web.xml去配置和定义我们的对象组件显然是不灵活和不方便扩展的,由于我们系统中将会需要配置很多个不同的对象资源,比如控制器,View对象,HandlerMapping对象等等,如何对它们进行管理,如何能让我们的前端控制器访问和利用到到它们便是我们不得不面对的问题。还好,现在有了Spring,现在很多流行的MVC框架都支持使用Spring对自己容器里的对象资源进行管理。尽管Spring千好万好,我们这里还是决定不使用它,而是自己来写一个对象容器来管理我们的相关资源,这样我们不仅可以了解对象资源配置管理的细节,还可以顺带学习一下Spring等IOC容器的实现原理。当然,我们这里的实现方案将会尽可能的简单。
如下便是我们的WebApplicationContext类的实现,它能够自动查找WEB-INF路径下所有以config结尾的xml文件,并把其中定义的对象抽取出来,放到Application作用域中,由于我们这里只是个Sample,不需要考虑太多的并发的情况,所有对象的类型,我们都是用Singleton,也就是定义的每个对象都为所有的请求和Servlet共享。 WebApplicationContext中还定义了一个很有用的方法,beansOfType(Class<T>),该方法用于查找出系统中定义的所有的属于当前类型的所有对象资源。

[java] view plaincopy
  1. package com.google.mvc.web.context;  
  2.   
  3. import java.io.InputStream;  
  4. import java.lang.reflect.Method;  
  5.   
  6. import java.util.HashMap;  
  7. import java.util.Locale;  
  8. import java.util.Map;  
  9. import java.util.Set;  
  10. import java.util.concurrent.ConcurrentHashMap;  
  11.   
  12. import javax.servlet.ServletContext;  
  13. import javax.xml.parsers.DocumentBuilder;  
  14. import javax.xml.parsers.DocumentBuilderFactory;  
  15. import javax.xml.parsers.ParserConfigurationException;  
  16.   
  17. import org.apache.log4j.Logger;  
  18. import org.w3c.dom.Document;  
  19. import org.w3c.dom.Element;  
  20. import org.w3c.dom.NodeList;  
  21.   
  22. public class WebApplicationContext {  
  23.       
  24.     private static final Logger LOGGER = Logger.getLogger(WebApplicationContext.class);   
  25.     private static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".CONTEXT";  
  26.     private Map<String, Object> cacheMap;  
  27.     private ServletContext servletContext;  
  28.     private DocumentBuilder builder;      
  29.   
  30.     public WebApplicationContext(ServletContext servletContext) {  
  31.         this.servletContext = servletContext;                 
  32.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  33.         try {  
  34.             builder = factory.newDocumentBuilder();  
  35.         } catch (ParserConfigurationException e) {  
  36.             LOGGER.error("Can't load dom builder", e);  
  37.         }  
  38.     }  
  39.   
  40.     public void init() {          
  41.         ServletContext context = getServletContext();  
  42.         Set<?> set = context.getResourcePaths("/WEB-INF");  
  43.         Object map = servletContext.getAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE);  
  44.         if (map != null) {  
  45.             cacheMap = (Map<String, Object>) map;  
  46.         } else {  
  47.             cacheMap = new ConcurrentHashMap<String, Object>();  
  48.             servletContext.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, cacheMap);             
  49.             for (Object o : set) {  
  50.                 String path = (String) o;  
  51.                 if (path.endsWith("config.xml")) {  
  52.                     try {                         
  53.                         loadResource(servletContext.getResourceAsStream(path));  
  54.                     } catch (Exception ex) {  
  55.                         LOGGER.error("Can't load resource " + path);  
  56.                     }  
  57.                 }  
  58.             }  
  59.         }  
  60.     }  
  61.       
  62.     private void loadResource(InputStream resource) throws Exception{  
  63.         Document doc = builder.parse(resource);  
  64.         Element root = doc.getDocumentElement();  
  65.           
  66.         NodeList nodeList = root.getElementsByTagName("bean");    
  67.         for(int i = 0; i < nodeList.getLength(); i++){             
  68.             Element el = (Element)nodeList.item(i);           
  69.             String id = el.getAttribute("id");  
  70.             String className = el.getAttribute("class");              
  71.             Class<?> clazz = this.getClass().getClassLoader().loadClass(className);  
  72.             Object o = createBean(id, clazz);             
  73.             NodeList propertyList = el.getElementsByTagName("property");  
  74.             for(int j = 0; j < propertyList.getLength(); j++){  
  75.                 Element prop = (Element)propertyList.item(j);                 
  76.                 String methodName = getMethodName(prop.getAttribute("name"));                 
  77.                 Method m = clazz.getMethod(methodName, String.class);                 
  78.                 String property = prop.getAttribute("value");  
  79.                 Object dependObject = cacheMap.get(property);  
  80.                 if(dependObject != null){  
  81.                     m.invoke(o, dependObject);  
  82.                 } else {  
  83.                     m.invoke(o, property);  
  84.                 }                         
  85.             }             
  86.             cacheMap.put(id, o);  
  87.         }         
  88.     }  
  89.       
  90.     protected String getMethodName(String methodName){  
  91.         StringBuilder sb = new StringBuilder();  
  92.         sb.append("set");  
  93.         sb.append(methodName.substring(01).toUpperCase(Locale.US));  
  94.         sb.append(methodName.substring(1));  
  95.         return sb.toString();  
  96.     }  
  97.       
  98.     public Object createBean(Class<?> clazz) throws Exception{          
  99.         return createBean(clazz.getCanonicalName(), clazz);  
  100.     }  
  101.       
  102.     public Object createBean(String name, Class<?> clazz) throws Exception{             
  103.         Object o = cacheMap.get(name);        
  104.         if(o == null){  
  105.             o = clazz.newInstance();  
  106.             if(o instanceof WebApplicationContextAware){  
  107.                 ((WebApplicationContextAware)o).setWebApplicationContext(this);  
  108.             }  
  109.             cacheMap.put(name, o);    
  110.         }     
  111.         LOGGER.info(name + "=" + clazz.getCanonicalName());  
  112.         return o;  
  113.     }  
  114.       
  115.     public Object getBean(String beanName){  
  116.         return servletContext.getAttribute(beanName);  
  117.     }  
  118.       
  119.     public ServletContext getServletContext() {  
  120.         return servletContext;  
  121.     }  
  122.   
  123.     public void setServletContext(ServletContext servletContext) {  
  124.         this.servletContext = servletContext;  
  125.     }  
  126.       
  127.     public <T> Map<String, T> beansOfType(Class<T> clazz){  
  128.         Map<String, T> map = new HashMap<String, T>();  
  129.         for(String key : cacheMap.keySet()){  
  130.             Object o = cacheMap.get(key);  
  131.             if(clazz.isAssignableFrom(o.getClass())){  
  132.                 map.put(key, (T)o);  
  133.             }  
  134.         }  
  135.         return map;  
  136.     }  
  137.   
  138. }  

我们再来看一下*.config.xml文件里对象资源的定义示例:

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans>     
  3.     <bean id="ControllerAdapter" class="com.google.mvc.web.servlet.mvc.ControllerHandlerAdapter" />    
  4.     <bean id="HttpRequestAdapter" class="com.google.mvc.web.servlet.mvc.HttpRequestHandlerAdapter" />   
  5.     <bean id="ViewResolver" class="com.google.mvc.web.servlet.mvc.DefaultViewResolver">  
  6.         <property name="viewClass" value="com.google.mvc.web.servlet.mvc.InternalResourceView"/>  
  7.         <property name="prefix" value="/WEB-INF/"/>  
  8.         <property name="suffix" value=".jsp"/>  
  9.     </bean>   
  10.     <bean id="login.do" class="com.google.mvc.web.sample.LoginController" />  
  11.     <bean id="hello.do" class="com.google.mvc.web.sample.HelloController" />     
  12.     <bean id="404" class="com.google.mvc.web.servlet.mvc.HandlerFor404" />   
  13.   
  14. </beans>  

如果哪个对象资源需要在运行过程中使用到WebApplicationContext的资源及方法,只需实现接口WebApplicationContextAware即可,一旦实现了该接口,当前的WebApplicationContext会被自动的注入到此对象资源中。

[java] view plaincopy
  1. package com.google.mvc.web.context;  
  2.   
  3. public interface WebApplicationContextAware {  
  4.       
  5.     void setWebApplicationContext(WebApplicationContext wac);  
  6.   
  7. }  

 

文章来源: http://blog.csdn.net/zhiqiangzhan/article/details/4762736

分享到:
评论

相关推荐

    Spring MVC开发配置文件 applicationContext

    Spring Web MVC开发 xml配置文件格式,无bean之类 Spring Web MVC开发配置文件 applicationContext

    xmljava系统源码-fortune-commons:FortuneCommons是一个专注于可重用Java组件各个方面的项目

    java系统源码 Fortune Commons Component 项目介绍 项目特色 项目深受Java 劝退师,Apache 和 Spring Cloud 等知名开源架构成员(Github:)的思想影响,本项目采用了现在普遍采用的自动化配置、注解化开发等特点,...

    Spring MVC之WebApplicationContext_动力节点Java学院整理

    主要介绍了Spring MVC之WebApplicationContext的相关资料,需要的朋友可以参考下

    在web容器(WebApplicationContext)中获取spring中的bean

    Spring把Bean放在这个容器中,普通的类在需要的时候,直接用getBean()方法取出

    Struts2+Spring3+MyBatis3完整实例

    网上的东西好大多都不能直接用,自己结合网上资料做了一个Struts2+Spring3+MyBatis3的测试工程,JUnit测试用例和WEB服务。 内涵完整jar包,解压直接可用,包括一个表文件。 Eclipse3.2+Tomcat/5.5+jdk1.5.0_17 - ...

    spring-web-5.3.6 jar包.rar

    这个jar文件包含Web应用开发时,用到Spring框架时所需的核心类, 包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。 spring的核心类,提供了核心HTTP...

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例

     这个jar文件包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。 (12) spring-webmvc.jar  这个...

    Spring获取webapplicationcontext,applicationcontext几种方法详解

    Spring获取webapplicationcontext,applicationcontext几种方法详解

    struts-2.3.8+spring-3.2.1+mybatis-3.2.2架构

    最新struts-2.3.8+spring-3.2.1+mybatis-3.2.2架构,包齐全,无冲突,Eclipse开发 导入工程即可 九月 18, 2013 11:39:01 上午 org.apache.catalina.core.AprLifecycleListener init INFO: The APR based Apache ...

    spring4.1核心包

    包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。 18. spring-webmvc-4.1.1.RELEASE.jar 包含...

    spring jar 包详解

    (11) spring-web.jar 这个jar文件包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、 Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。 (12) ...

    spring+springmvc+mybatis的整合

    WebApplicationContext acc = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()); ls = (LoginService) acc.getBean("MyService"); 而讲义上的实现: [java] view ...

    spring chm文档

    12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器中使用Hibernate的注意点 12.3. JDO ...

    spring源代码解析

    在这个上下文的基础上,和web MVC相关还会有一个上下文来保存控制器之类的MVC对象,这样就构成了一个层次化的上下文结构。在web容器中启动Spring应用程序就是一个建立这个上下文体系的过程。Spring为web应用提供了上...

    Spring中文帮助文档

    12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器中使用Hibernate的注意事项 12.3. ...

    Spring API

    12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器中使用Hibernate的注意事项 12.3. ...

    Spring TestContext

    Spring TestContext Framework是spring-test模块中提供的一个测试框架,能够用于单元测试和集成测试。

    SpringMVC中的RootApplicationContext上下文和WebApplicationContext上下文,通过注解配置SpringMVC的完整解决方案

    注解配置SpringMVC原理简述1. 准备知识1.1 两个应用上下文1.2 ServletContext配置方法(Configuration Methods)1.3 运行时插拔1.4 SpringServletContainerInitializer1.4.1 AbstractContextLoaderInitializer1.4.2 ...

    Spring.html

    概念:面向切面编程,在不改变源码的情况下对方法进行增强,抽取横切关注点(日志处理,事务管理,安全检查,性能测试等等),使用AOP进行增强,使程序员只需要关注与业务逻辑编写. 专业术语 目标Target:需要增强的类 ...

    第14章:网络编程(day20).zip

    [[03 08:58:22,466 INFO ] org.springframework.context.support.AbstractApplicationContext.prepareRefresh(AbstractApplicationContext.java:511) - Refreshing WebApplicationContext for namespace 'hessian-...

Global site tag (gtag.js) - Google Analytics