springboot webmvc初始化:一个登陆异常引出的话题
1.场景复现:
一个登陆异常引出的问题。
我们通过精心组织组件扫描的方式,来装配不同的子模块,形成一个可运行的应用;
在载入某个子模块后,我们发现应用虽然正常启动,但尝试登陆的时候,出现一个很异常的异常,部分stacktrace如下:
processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface org.springframework.mobile.device.Device] with root cause java.lang.NoSuchMethodException: org.springframework.mobile.device.Device.<init>() |
异常栈部分调用关系如下:

如果移除子模块,应用启动后,同一个入口会触发的正常调用栈如下:

换句话说,异常情况和正常情况,走了不同的处理链。
1.我们初步怀疑是包冲突,但验证后排除掉这个问题;
2.然后继续通过调试代码,分析发现加入子模块后,启动的
HandlerMethodArgumentResolver 实例有27个;
而不加入子模块,启动的
HandlerMethodArgumentResolver 实例有33个,多了几个resolver,其中包括DeviceHandlerMethodArgumentResolver,看起来找到好的线索了;
3.根据线索,怀疑是配置问题,首先怀疑的是安全方面的配置问题;但一直测试分析没有得到结果;
4.后续,用排除法,发现此模块中去掉一个定义的配置类,问题就可以得到解决,这个配置如下::
Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
...
}
2.经过所有线索的梳理,这个问题产生的内在机制比较明确了:
HandlerMethodArgumentResolver
源码注释:
Strategy interface for resolving method parameters into argument values in the context of a given request.
简单可以理解为:解析方法参数的策略接口;通俗的理解为,(controller的)参数解析(构造)转换按这个接口来实现;
WebMvcConfigurationSupport
源码注释:
This is the main class providing the configuration behind the MVC Java config.
其中有一个方法:
@Bean |
简而言之,DeviceHandlerMethodArgumentResolver 实例是靠
WebMvcConfigurationSupport 提供的机制(模板函数),加载进容器处理链的;
DelegatingWebMvcConfiguration
实际上,spring 依靠
DelegatingWebMvcConfiguration 自动检测并代理实现所有的自定义配置
/**
* A subclass of {@code WebMvcConfigurationSupport} that detects and delegates
* to all beans of type {@link WebMvcConfigurer} allowing them to customize the
* configuration provided by {@code WebMvcConfigurationSupport}. This is the
* class actually imported by {@link EnableWebMvc @EnableWebMvc}.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
WebMvcAutoConfiguration
DelegatingWebMvcConfiguration 的实例创建,是通过下面这个类
WebMvcAutoConfiguration 导入,但是有个条件:当容器内不存在 WebMvcConfigurationSupport 的实例时
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
所以,当我们自己子模块的代码,有这个自定义配置时
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
系统默认的webmvc 配置行为将会被覆盖;
springboot webmvc初始化:一个登陆异常引出的话题的更多相关文章
- 基于SpringBoot如何实现一个点赞功能?
基于SpringBoot如何实现一个点赞功能? 解析: 基于 SpringCloud, 用户发起点赞.取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储 ...
- ZeroMQ接口函数之 :zmq_msg_init - 初始化一个空的ZMQ消息结构
ZeroMQ 官方地址 :http://api.zeromq.org/4-1:zmq_msg_init zmq_msg_init(3) ØMQ Manual - ØMQ/3.2.5 Name zmq_ ...
- ZeroMQ接口函数之 :zmq_msg_init_data - 从一个指定的存储空间中初始化一个ZMQ消息对象的数据
ZeroMQ 官方地址 :http://api.zeromq.org/4-1:zmq_msg_init_data zmq_msg_init_data(3) ØMQ Manual - ØMQ/3.2.5 ...
- [Android]ViewPager如何只初始化一个页面
使用过ViewPager的应该都知道,ViewPager的setoffscreenpagelimit()方法,使用该方法可以设置在ViewPager滑动时,左右两侧各保存多少个页面,那我们直接设置se ...
- 如何初始化一个iOS原生地图
/** 初始化一个mapView 需导入 #import <MapKit/MapKit.h> - returns: 返回一个mapView对象 */ mapView = [[MKMapV ...
- 标准程序员系列-Github篇-初始化一个代码仓库
下面将一步步介绍怎样使用GitHub来初始化一个项目的版本控制仓库: 1. 到GitHub上注册自己的账号:https://github.com/ 2. 创建第一个代码仓库一个仓库相当于一个项目的代码 ...
- @Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常。
@Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationEx ...
- 第5章 不要让线程成为脱缰的野马(Keeping your Threads on Leash) ----初始化一个线程
使用线程的一个常见问题就是如何能够在一个线程开始运行之前,适当地将它初始化.初始化最常见的理由就是为了调整优先权.另一个理由是为了在SMP 系统中设定线程比较喜欢的 CPU.第10 章谈到 MFC 时 ...
- tkinter如何设置界面消失 当制作一个登陆界面时,登陆成功之后,如何让登陆界面本身消失
tkinter如何设置界面消失 当制作一个登陆界面时,登陆成功之后,如何让登陆界面本身消失 if querySQL.checkAll():#用户名和密码都输入正确 self.root.withdraw ...
随机推荐
- mysql时间相加函数DATE_ADD()
mysql中的DATE_ADD()函数 1.定义:函数向日期添加指定的时间间隔. 2.语法:DATE_ADD(date,INTERVAL expr type) date 参数是合法的日期表达式.exp ...
- 隐藏软键盘(解决自定义Dialog中无法隐藏的问题)
/** * Dialog中隐藏软键盘不管用 * @param activity */ public static void HideSoftKeyBoard(Activity activity){ t ...
- opencv学习之路(35)、SURF特征点提取与匹配(三)
一.简介 二.opencv中的SURF算法接口 三.特征点匹配方法 四.代码 1.特征点提取 #include "opencv2/opencv.hpp" #include < ...
- raphael参数说明
大纲 :first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-pr ...
- Linux 系统调用(system call)
1 系统调用:(SYSTEM CALL) 操作系统(operating system)内核中有一组实现系统功能的过程,系统调用就是对上述过程的调用.程序员利用系统调用,向OS提出服务请求,由OS代为完 ...
- Cent OS6下SS+BBR+改SSH端口
SS+BBR+改SSH端口 (一)搭建SS wget --no-check-certificate -O shadowsocks-libev.sh https://raw.githubusercont ...
- 0 vs null
看图说话 0 如图所示: 0 表示有纸(值), 但是纸(值)是0. 所以取纸(值)的时可以取, 但是没法用. null 如图所示: null 表示没有纸(值), 是真的啥都没有, 现在你抽纸的时候会出 ...
- C# 启动外部进程
C# 启动外部进程: var processInfo = new ProcessStartInfo(fullName); processInfo.UseShellExecute = false; pr ...
- hiho#1513 : 小Hi的烦恼 五维偏序
hiho#1513 : 小Hi的烦恼 五维偏序 链接 hiho 思路 高维偏序用bitset,复杂度\((\frac{n^2}{32})\) 代码 #include <bits/stdc++.h ...
- (转)Extracting knowledge from knowledge graphs using Facebook Pytorch BigGraph.
Extracting knowledge from knowledge graphs using Facebook Pytorch BigGraph 2019-04-27 09:33:58 This ...