BeanNameUrlHandlerMapping初始化原理

发布时间:2024年01月20日
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);
                            }
                        }
                    }
                }
            }
        }
    }
}

文章来源:https://blog.csdn.net/JavaMyDream/article/details/135723624
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。