发布时间:2023-02-11 文章分类:编程知识 投稿人:李佳 字号: 默认 | | 超大 打印

SpringMVC底层机制简单实现-02

https://github.com/liyuelian/springmvc-demo.git

4.任务3-从web.xml动态获取容器配置文件

4.1分析

任务3:MyDispatcherServlet (自定义的前端分发器)在创建并初始化自定义的spring容器时,可以动态地从web.xml中获取到配置的容器文件。

我们之前实现的时候,是直接在 MyWebApplicationContext 中指定要读取的容器文件。

day06-SpringMVC底层机制简单实现-02

改进:在web.xml中通过init-param指定容器文件,然后通过读取web.xml获取即可。这样可以动态地读取容器文件,不需要改变源代码。

day06-SpringMVC底层机制简单实现-02

4.2代码实现

(1)修改 MyDispatcherServlet 的 init 方法。通过 ServletConfig 对象,获取 Servlet 的初始化参数 init-param,将该参数的值传入 spring 容器的初始化方法。

部分代码:

@Override
public void init(ServletConfig servletConfig) throws ServletException {
    /** web.xml文件,前端控制器的配置中:
     *  <init-param>
     *     <param-name>contextConfigLocation</param-name>
     *     <param-value>classpath:myspringmvc.xml</param-value>
     *  </init-param>
     */
    //configLocation ==> classpath:myspringmvc.xml
    String configLocation =
            servletConfig.getInitParameter("contextConfigLocation");
    //初始化ioc容器,传入指定的spring配置文件
    myWebApplicationContext = new MyWebApplicationContext(configLocation);
    myWebApplicationContext.init();
    //调用 initHandlerMapping(),完成url和控制器方法的映射
    initHandlerMapping();
    //测试输出 handlerList
    System.out.println("handlerList输出的结果=" + handlerList);
}

(2)修改 MyApplicationContext 自定义spring 容器,额外提供一个带参构造器,用于获取传入的 容器配置文件名,然后传给 MyApplicationContext 的 init() 方法去初始化。

部分代码:

//无参构造器
public MyWebApplicationContext() {
}
//表示spring容器配置文件名
private String configLocation;
//带参构造器
public MyWebApplicationContext(String configLocation) {
    this.configLocation = configLocation;
}
/**
 * 该方法完成对自己的 spring容器的初始化
 */
public void init() {
    //configLocation的值是 classpath:myspringmvc.xml
    // 按冒号分割,取索引为 1的子串:myspringmvc.xml
    String basePackage =
            XMLParse.getBasePackage(configLocation.split(":")[1]);
    String[] basePackages = basePackage.split(",");
    if (basePackages.length > 0) {
        //遍历这些包
        for (String pack : basePackages) {
            scanPackage(pack);
        }
    }
    System.out.println("扫描后的路径classFullPathList=" + classFullPathList);
    //将扫描到的类反射到ioc容器
    executeInstance();
    System.out.println("扫描后的ioc容器=" + ioc);
}
//scanPackage方法,略..该方法完成对包的扫描
//executeInstance方法,略..该方法将扫描到的类,在满足条件的情况下进行反射,并放入到ioc容器中