在本系列的第一篇,我剖析了DispatcherServlet的初始化过程,但还有很多东西没有说清楚,比如HandlerMapping的具体初始化,本篇就来厘清它。
如果你没有显式指定(通过xml配置文件或者Annotation)你要用的HandlerMapping类的话,DispatcherServlet默认会去classpath底下找DispatcherServlet.properties这个文件,然后从这个文件中读取出HandlerMapping类,并实例化对象。
DispatcherServlet.properties文件如下:(这里用的是4.3.9.release版本的Spring-MVC,里面的那个DefaultAnnotationHandlerMapping已经被Deprecated了,更新的版本是用的RequestMappingHandlerMapping,但这并不影响我们的分析):
我们先看一下DefaultAnnotationHandlerMapping类的继承关系: 我们看到这个DefaultAnnotationHandlerMapping最后其实是实现了ApplicationContextAware这个接口,我们要记住这个,因为它在后面会发挥重要的作用。
我们这里关注的是,究竟DefaultAnnotationHandlerMapping什么时候去将Request与Handler的Mapping关系初始化。在DefaultAnnotationHandlerMapping类里面,没有看到有这个过程,在它的父类AbstractDetectingUrlHandlerMapping里面看到了initApplicationContext()这个方法,看上去是我们要找的:
但这个initApplicationContext方法究竟是什么时候被调用的呢? 我们再回过头来看一下DefaultAnnotationHandlerMapping对象是怎样创建出来的: 我们可以看到它是调到了Spring的AbstractAutowireCapableBeanFactory的createBean方法来创建对象: 到这里,调用了doCreateBean方法,这个方法比较长,我们直奔主题吧,秘密就藏在doCreateBean方法里面调用的initializeBean方法里面(从名字已经能看出,它是负责初始化的):
这个方法也比较枯燥,我们要看的是它里面调用的applyBeanPostProcessorsBeforeInitialization方法: 我们可以看到这个方法是一一调用ApplicationContext里面的所有BeanPostProcessor的postProcessorBeforeInitialization 方法,这些BeanPostProcessor都是在AbstractApplicationContext的refresh方法里面通过调用prepareBeanFactory方法注册进来的: 其中我们要关注的是ApplicationContextAwareProcessor,我们看一下它的postProcessBeforeInitialization方法: 再看它里面调用的invokeAwareInterfaces方法: 这时候,我们可以回想到我在前文中提到的我们要记住的:“我们看到这个DefaultAnnotationHandlerMapping最后其实是实现了ApplicationContextAware这个接口”,所以,我们终于看到在初始化DefaultAnnotationHandlerMapping这个对象的时候,因为它实现了ApplicationContextAware接口,所以它就会通过ApplicationContextAwareProcessor来调用它的setApplicationContext方法,它的setApplicationContext方法继承于ApplicationObjectSupport: 我们可以看到在setApplicationContext方法里面就会去调用initApplicationContext这个方法! 这就回答我们文章一开始的那个问题,什么时候调用initApplicationContext方法来初始化Request与Handler的Mapping映射!