电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因

瀏覽:19日期:2023-05-08 08:52:26

前言

本來沒有計劃這一篇文章的,只是在看完SpringBoot核心原理后,突然想到之前開發(fā)中遇到的MVC自動失效的問題,雖然網(wǎng)上有很多文章以及官方文檔都說明了原因,但還是想親自看一看,本以為很簡單的事情,沒想到卻引發(fā)出一個較復(fù)雜的問題,請教了很多人都沒有得到結(jié)果,網(wǎng)上文章也沒有寫清楚的,最后還是自己搞了很久才弄明白的,此篇主要記錄自己的一個分析過程。

正文

引出問題

全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因

上面是SpringBoot MVC的自動配置,問題是這樣的,當(dāng)我們需要自己配置MVC時,有三種選擇:

實(shí)現(xiàn)WebMvcConfigurer接口 繼承WebMvcConfigurerAdapter類 繼承WebMvcConfigurationSupport類

在老版本中我們常用的做法就是繼承WebMvcConfigurerAdapter類,這個類本身是實(shí)現(xiàn)了WebMvcConfigurer接口的,因?yàn)槔习姹綣DK接口沒有默認(rèn)方法,直接實(shí)現(xiàn)WebMvcConfigurer比較繁瑣,而后來接口可以有默認(rèn)方法了,WebMvcConfigurerAdapter就被標(biāo)記為過時了,所以我們現(xiàn)在配置MVC只需要實(shí)現(xiàn)WebMvcConfigurer接口或者繼承WebMvcConfigurationSupport,但是后者會導(dǎo)致SpringBoot的配置失效,因?yàn)樵谧詣优渲妙惿嫌蠤ConditionalOnMissingBean(WebMvcConfigurationSupport.class)這樣一個注解,表示沒有WebMvcConfigurationSupport類及其子類的實(shí)例時才會加載自動配置(另外使用@EnableWebMvc注解也會導(dǎo)致自動配置失效)。

MVC自動配置失效的原因就是這個了,基本上所有網(wǎng)上的文章分析到這一步也就完了,但是注意上圖我畫的紅方框,在這個自動配置類中有兩個靜態(tài)內(nèi)部類,我們知道靜態(tài)內(nèi)部類是優(yōu)于外部類加載的(SpringBoot自動配置大量使用了此特性),而其中EnableWebMvcConfiguration這個類,我注意到它是繼承自DelegatingWebMvcConfiguration,而DelegatingWebMvcConfiguration又繼承自WebMvcConfigurationSupport類,相信看到這你也應(yīng)該會有疑惑了,為什么這個配置類沒有導(dǎo)致自動配置失效,而我們自己實(shí)現(xiàn)的就會?

分析過程

我知道配置類的解析注冊是在ConfigurationClassPostProcessor類中,而這個類我前面的文章多次分析過,雖然這個類的實(shí)現(xiàn)流程不難,但細(xì)節(jié)非常繞,所以之前沒有深挖。遇到這個問題時,我首先想的是對這個類的理解不夠深刻,因此第一時間想到仔細(xì)研究這個類,在花費(fèi)了大量時間斷點(diǎn)分析后,卻沒有太大的收獲。

接著我又想,是不是配置類的注冊順序在自動配置的后面。這里我就犯了一個顯而易見的錯誤,因?yàn)槲铱紤]的是注冊的順序,不是實(shí)例化。因?yàn)镃onditionalOnMissingBean注解是沒有指定bean的實(shí)例時才會去加載,而我腦海里當(dāng)時想成了ConditionalOnMissingClass。所以我在DefaultListableBeanFactory中的registerBeanDefinition和preInstantiateSingletons方法上打上了斷點(diǎn),力圖確認(rèn)注冊順序如我所想:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);if (existingDefinition != null) {....this.beanDefinitionMap.put(beanName, beanDefinition);}else {if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;removeManualSingletonName(beanName);}}else {// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);removeManualSingletonName(beanName);}this.frozenBeanDefinitionNames = null;}}public void preInstantiateSingletons() throws BeansException {List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);....}

全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因

但結(jié)果beanDefinitionNames中的順序卻是兩個靜態(tài)內(nèi)部類在前,也就是說靜態(tài)內(nèi)部類肯定是在外部類之前就注冊到IOC容器中了,這下我就傻了。但幸好也是因此,否則我就該認(rèn)為這就是結(jié)果了。最終我想到了應(yīng)該看類的實(shí)例化順序,但是正常情況下類的實(shí)例化順序就是上面的斷點(diǎn)圖中的順序,我想會不會是有什么類依賴了WebMvcAutoConfiguration,導(dǎo)致它提前實(shí)例化。于是我將斷點(diǎn)又設(shè)置到AbstractBeanFactory中的doGetBean方法并加上了條件(不得不說idea的功能非常強(qiáng)大,回到上一個調(diào)用點(diǎn)、給斷點(diǎn)設(shè)置條件、調(diào)用堆棧信息大大節(jié)省了我的調(diào)試時間):

全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因

然后啟動項(xiàng)目就可以看到首先實(shí)例化的果然是WebMvcAutoConfiguration類,這樣就搞清楚了為什么EnableWebMvcConfiguration沒有導(dǎo)致自動配置失效。

但是還沒完,為什么自動配置類會在靜態(tài)內(nèi)部類之前實(shí)例化呢?是由誰觸發(fā)的呢?繼續(xù)深入,這時我想到了看調(diào)用棧:

全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因

粗略看一下調(diào)用棧信息,如果對Spring源碼熟悉,可以發(fā)現(xiàn)自動配置類的實(shí)例化是在instantiateUsingFactoryMethod中觸發(fā)的:

String factoryBeanName = mbd.getFactoryBeanName();if (factoryBeanName != null) {if (factoryBeanName.equals(beanName)) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,'factory-bean reference points back to the same bean definition');}factoryBean = this.beanFactory.getBean(factoryBeanName);if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {throw new ImplicitlyAppearedSingletonException();}factoryClass = factoryBean.getClass();isStatic = false;}else {// It’s a static factory method on the bean class.if (!mbd.hasBeanClass()) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,'bean definition declares neither a bean class nor a factory-bean reference');}factoryBean = null;factoryClass = mbd.getBeanClass();isStatic = true;}

這段代碼在bean實(shí)例化的那一篇分析過,這個方法的作用是通過factoryMethod實(shí)例化當(dāng)前的BeanDefinition,而實(shí)例化該BD優(yōu)先會實(shí)例化factoryBeanName屬性指向的Bean,這里的factoryBeanName就是org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,factoryMethod則是formContentFilter,而這兩個屬性的設(shè)置則是在ConfigurationClassPostProcessor解析@Configuration和@Bean就設(shè)置好了(@Bean標(biāo)注的方法名會設(shè)置到factoryMethod,而該方法所在配置類的名稱就是factoryBeanName),這里就不展開分析了。

@Configuration(proxyBeanMethods = false)@ConditionalOnWebApplication(type = Type.SERVLET)@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,ValidationAutoConfiguration.class })public class WebMvcAutoConfiguration {public static final String DEFAULT_PREFIX = '';public static final String DEFAULT_SUFFIX = '';private static final String[] SERVLET_LOCATIONS = { '/' };@Bean@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)@ConditionalOnProperty(prefix = 'spring.mvc.hiddenmethod.filter', name = 'enabled', matchIfMissing = false)public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {return new OrderedHiddenHttpMethodFilter();}@Bean@ConditionalOnMissingBean(FormContentFilter.class)@ConditionalOnProperty(prefix = 'spring.mvc.formcontent.filter', name = 'enabled', matchIfMissing = true)public OrderedFormContentFilter formContentFilter() {return new OrderedFormContentFilter();}......}

formContentFilter就是在MVC自動配置類中配置的,默認(rèn)是加載的,而filter就不用多說了,在Tomcat啟動后就會觸發(fā)初始化,追蹤調(diào)用棧也可以看到。另外我們還看到自動配置類中還配置了一個HiddenHttpMethodFilter,不過這個默認(rèn)是不加載的,所以我們只要在application.properties中配置了如下屬性,自動配置類就不會實(shí)例化了,但是兩個靜態(tài)內(nèi)部類的實(shí)例化還是不會受影響的。

spring.mvc.formcontent.filter.enabled=false

總結(jié)

該問題只是出于興趣研究,雖然耗費(fèi)了大量的時間和精力,但收獲不少,加深了對Spring源碼的理解,也修正了之前的一些錯誤理解,另外對于源碼更多的是要自己去研究,不能只看一兩篇文章或聽別人說,只有自己親手調(diào)試過才能知道自己的理解是否正確。

到此這篇關(guān)于全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因的文章就介紹到這了,更多相關(guān)SpringBoot MVC自動配置失效內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 代做标书-代写标书-专业标书文件编辑-「深圳卓越创兴公司」 | 污水提升器,污水提升泵,地下室排水,增压泵,雨水泵,智能供排水控制器-上海智流泵业有限公司 | 万濠影像仪(万濠投影仪)百科-苏州林泽仪器 | 新能源汽车电机定转子合装机 - 电机维修设备 - 睿望达 | 软启动器-上海能曼电气有限公司| WTB5光栅尺-JIE WILL磁栅尺-B60数显表-常州中崴机电科技有限公司 | 硫酸钡厂家_高光沉淀硫酸钡价格-河南钡丰化工有限公司 | 全自动五线打端沾锡机,全自动裁线剥皮双头沾锡机,全自动尼龙扎带机-东莞市海文能机械设备有限公司 | 上海律师咨询_上海法律在线咨询免费_找对口律师上策法网-策法网 广东高华家具-公寓床|学生宿舍双层铁床厂家【质保十年】 | 注塑模具_塑料模具_塑胶模具_范仕达【官网】_东莞模具设计与制造加工厂家 | 工业rfid读写器_RFID工业读写器_工业rfid设备厂商-ANDEAWELL | 三防漆–水性三防漆–水性浸渍漆–贝塔三防漆厂家 | 防水接头-电缆防水接头-金属-电缆密封接头-不锈钢电缆接头 | 宁夏档案密集柜,智能密集柜,电动手摇密集柜-盛隆柜业宁夏档案密集柜厂家 | 回转窑-水泥|石灰|冶金-巩义市瑞光金属制品有限责任公司 | 河南卓美创业科技有限公司-河南卓美防雷公司-防雷接地-防雷工程-重庆避雷针-避雷器-防雷检测-避雷带-避雷针-避雷塔、机房防雷、古建筑防雷等-山西防雷公司 | 粤丰硕水性环氧地坪漆-防静电自流平厂家-环保地坪涂料代理 | 不锈钢拉手厂家|浴室门拉手厂家|江门市蓬江区金志翔五金制品有限公司 | 德州万泰装饰 - 万泰装饰装修设计软装家居馆 | 电池挤压试验机-自行车喷淋-车辆碾压试验装置-深圳德迈盛测控设备有限公司 | 翻斗式矿车|固定式矿车|曲轨侧卸式矿车|梭式矿车|矿车配件-山东卓力矿车生产厂家 | 脑钠肽-白介素4|白介素8试剂盒-研域(上海)化学试剂有限公司 | 造价工程师网,考试时间查询,报名入口信息-网站首页 | 南溪在线-南溪招聘找工作、找房子、找对象,南溪综合生活信息门户! | 合金ICP光谱仪(磁性材料,工业废水)-百科| Dataforth隔离信号调理模块-信号放大模块-加速度振动传感器-北京康泰电子有限公司 | 脱硝喷枪-氨水喷枪-尿素喷枪-河北思凯淋环保科技有限公司 | 天然鹅卵石滤料厂家-锰砂滤料-石英砂滤料-巩义东枫净水 | 铁盒_铁罐_马口铁盒_马口铁罐_铁盒生产厂家-广州博新制罐 | 接地电阻测试仪[厂家直销]_电缆故障测试仪[精准定位]_耐压测试仪-武汉南电至诚电力设备 | 瓶盖扭矩仪(扭力值检测)-百科| 除尘布袋_液体过滤袋_针刺毡滤料-杭州辉龙过滤技术有限公司 | 美国HASKEL增压泵-伊莱科elettrotec流量开关-上海方未机械设备有限公司 | 精密机械零件加工_CNC加工_精密加工_数控车床加工_精密机械加工_机械零部件加工厂 | 阻燃剂-氢氧化镁-氢氧化铝-沥青阻燃剂-合肥皖燃新材料 | 超声波反应釜【百科】-以马内利仪器 | 学习安徽网| 外观设计_设备外观设计_外观设计公司_产品外观设计_机械设备外观设计_东莞工业设计公司-意品深蓝 | 尼龙PA610树脂,尼龙PA612树脂,尼龙PA1010树脂,透明尼龙-谷骐科技【官网】 | 隔离变压器-伺服变压器--输入输出电抗器-深圳市德而沃电气有限公司 | 合肥办公室装修 - 合肥工装公司 - 天思装饰 |