class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping
extends AbstractUrlHandlerMapping
extends AbstractHandlerMapping
extends ApplicationObjectSupport
implements ApplicationContextAware
{
public final void setApplicationContext(@Nullable ApplicationContext context){
this.applicationContext = context;
this.initApplicationContext(context);{
// 默认空实现,将当前持有的拦截器集合给子类去继承
// 这里的interceptors实一个Object的集合,保存了不同类型的拦截器,例如WebRequestInterceptor,HandlerInterceptor
extendInterceptors(this.interceptors);
// 将Spring容器中存在的MappedInterceptor类型的拦截器保存起来到adaptedInterceptors
// adaptedInterceptors这个集合才是真正的HandlerInterceptor
detectMappedInterceptors(this.adaptedInterceptors);
// 初始化拦截器
initInterceptors();{
if (!this.interceptors.isEmpty()) {
for (int i = 0; i < this.interceptors.size(); i++) {
Object interceptor = this.interceptors.get(i);
// 适配拦截器
HandlerInterceptor adapter= adaptInterceptor(interceptor);{
if (interceptor instanceof HandlerInterceptor) {
return (HandlerInterceptor) interceptor;
}
if (interceptor instanceof WebRequestInterceptor) {
return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
}
}
// 保存到已适配的拦截器中
this.adaptedInterceptors.add(adapter);
}
}
}
}
// 查找保存处理符合条件的的Handler
detectHandlers();{
ApplicationContext applicationContext = obtainApplicationContext();
// 找到所有的Bean
String[] beanNames = applicationContext.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
// 根据现在要处理的beanName名称是以"/"开头,所以来确定访问的URL
// 可能会出现多个可以请求的url,例如@Bean({"/a","/b"}),/a,/b都能访问,配置了别名
String[] urls = determineUrlsForHandler(beanName);{
List<String> urls = new ArrayList<>();
if (beanName.startsWith("/")) {
urls.add(beanName);
}
// 如果给bean配置了名别,那么别名也可以访问
// beanName可以配置多个(用逗号或分号或空格隔开),@Bean({"/a","/b"})
String[] aliases = obtainApplicationContext().getAliases(beanName);
for (String alias : aliases) {
if (alias.startsWith("/")) {
urls.add(alias);
}
}
return StringUtils.toStringArray(urls);
}
if (!ObjectUtils.isEmpty(urls)) {
// 注册handler
registerHandler(urls, beanName);{
for (String urlPath : urlPaths) {
// 一一注册
registerHandler(urlPath, beanName);{
// 如果不是懒加载的的Handler
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
ApplicationContext applicationContext = obtainApplicationContext();
// 是单例的才能获取出对应的Bean
if (applicationContext.isSingleton(handlerName)) {
resolvedHandler = applicationContext.getBean(handlerName);
}
}
// 看看对应的url是否已经被映射了,也就是有对应的handler
Object mappedHandler = this.handlerMap.get(urlPath);
// 如果再次出现,表示handler冲突了,抛异常
if (mappedHandler != null && mappedHandler != resolvedHandler){
throw new IllegalStateException();
}
// 如果是根目录,使用单独的handler,因为根目录只有一个,没必要储存到映射表中,单独保存就行
if (urlPath.equals("/")) {
setRootHandler(resolvedHandler);
}
// 如果是通配符
if (urlPath.equals("/*")) {
// 使用默认的将当前的handler保存到defaultHandler中,和root类似
// 因为后面找不到对应的handler的时候,就会使用这个默认的handler,因为他可以处理任意请求
setDefaultHandler(resolvedHandler);
}
// 将handler与路径缓存起来,可以检验url存在多个handler的异常情况
// 后面获取handler的时候也是直接从map中获取
// 这个handlerMap就是存储这url->handler的映射,因为这种方式的url->handler是一一对应的
// 和RequestMapping不一样
this.handlerMap.put(urlPath, resolvedHandler);
}
}
}
}
}
}
}
}