springboot 初始化加载过程 WebMvcAutoConfiguration / MessageSourceAutoConfiguration / ErrorMvcAutoConfiguration
WebMvcAutoConfiguration : webmvc自动化配置
MessageSourceAutoConfiguration :国际化自动配置
ErrorMvcAutoConfiguration:统一异常处理自动配置
从其他博客粘过来的表格:
条件注解 | Condition处理类 | 实例 | 解释 |
---|---|---|---|
@ConditionalOnBean | OnBeanCondition | @ConditionalOnBean(DataSource.class) | Spring容器中不存在对应的实例生效 |
@ConditionalOnMissingBean | OnBeanCondition | @ConditionalOnMissingBean(name = "redisTemplate") | Spring容器中不存在对应的实例生效 |
@ConditionalOnSingleCandidate | OnBeanCondition | @ConditionalOnSingleCandidate(FilteringNotifier.class) |
Spring容器中是否存在且只存在一个对应的实例, 或者虽然有多个但 是指定首选的Bean生效 |
@ConditionalOnClass | OnClassCondition | @ConditionalOnClass(RedisOperations.class) | 类加载器中存在对应的类生效 |
@ConditionalOnMissingClass | OnClassCondition | @ConditionalOnMissingClass(RedisOperations.class) | 类加载器中不存在对应的类生效 |
@ConditionalOnExpression | OnExpressionCondition | @ConditionalOnExpression(“’${server.host}’==’localhost’”) | 判断SpEL 表达式成立生效 |
@ConditionalOnJava | OnJavaCondition | @ConditionalOnJava(JavaVersion.EIGHT) | 指定Java版本符合要求生效 |
@ConditionalOnProperty | OnPropertyCondition |
@ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”, matchIfMissing = true) |
应用环境中的属性满足条件生效 |
@ConditionalOnResource | OnResourceCondition | @ConditionalOnResource(resources=”mybatis.xml”) | 存在指定的资源文件生效 |
@ConditionalOnWebApplication | OnWebApplicationCondition | 当前应用是Web应用生效 | |
@ConditionalOnNotWebApplication | OnWebApplicationCondition | 当前应用不是Web应用生效 |
上面的扩展注解我们可以简单的分为以下几类:
- Bean作为条件:@ConditionalOnBean、@ConditionalOnMissingBean、@ConditionalOnSingleCandidate。
- 类作为条件:@ConditionalOnClass、@ConditionalOnMissingClass。
- SpEL表达式作为条件:@ConditionalOnExpression。
- JAVA版本作为条件: @ConditionalOnJava
- 配置属性作为条件:@ConditionalOnProperty。
- 资源文件作为条件:@ConditionalOnResource。
- 是否Web应用作为判断条件:@ConditionalOnWebApplication、@ConditionalOnNotWebApplication。
以上是理解springboot默认加载的基础。
1.
2.
3.
4.
5.
6.
7.截图放不下了,最终会指向 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
8. imports 局部截图。这里包含了springboot想为你加载的所有模块的 *AutoConfiguration
9.当然,这些自动配置类并不是全部都会用到,会经过筛选处理
10.现在我们看一下 WebMvcAutoConfiguration.. 如果满足这三个条件。就不会过滤掉,看看上面的筛选条件。
11.看看WebMvcAutoConfiguration 做了什么。 根据条件注解,看看加载 Bean的条件,。思考如何定义自己的 bean并替换它们吧!
12.自定义 WebMvcConfigurer 进行 默认配置类的扩展。这里代码仅供参考,主要讨论扩展原理

//@EnableWebMvc 加了这个会使Springmvc自动配置失效 @Configuration public class MyWebMvcConfigurer implements WebMvcConfigurer { /** * 添加视图控制器 * 立即访问 * <mvc:view-controller path="/" view-name="index" /> * * @param registry */ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/tuling").setViewName("hello"); } /** * 添加拦截器 * * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new TimeInterceptor()) //添加拦截器 .addPathPatterns("/**") // 拦截映射规则 .excludePathPatterns("/pages/**"); // 设置排除的映射规则 // 添加国际化拦截器 registry.addInterceptor(new LocaleChangeInterceptor()) .addPathPatterns("/**"); // 拦截映射规则 } /** * 全局CORS配置 * * @param * @Override public void addCorsMappings(CorsRegistry registry) { * registry.addMapping("/user/*") // 映射服务器中那些http接口运行跨域访问 * .allowedOrigins("http://localhost:8081") // 配置哪些来源有权限跨域 * .allowedMethods("GET","POST","DELETE","PUT"); // 配置运行跨域访问的请求方法 * } */ @Bean public LocaleResolver localeResolver() { CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver(); // 可以设置过期时间 cookieLocaleResolver.setCookieMaxAge(60 * 60 * 24 * 30); cookieLocaleResolver.setCookieName("locale"); return cookieLocaleResolver; } }
13.书接前文,还是在 WebMvcAutoConfiguration 里
WebMvcAutoConfigurationAdapter 通过
@Import(EnableWebMvcConfiguration.class) 导入 EnableWebMvcConfiguration
EnableWebMvcConfiguration 继承了 DelegatingWebMvcConfiguration
14。
DelegatingWebMvcConfiguration作为一个配置类,将容器里所有的 webMvcConfigurer 全部注入进了 configurers.
注意:重写的 WebMvcConfigurationSupport 方法,都是在处理 configurers
15. @EnableWebMvc. 是自动配置失效的原理
注意:13步里的 Configuration equivalent to @EnableWebMvc.
如下图:没有 WebMvcConfigurationSupport 类 WebMvcAutoConfiguration 才会生效
而 @EnableWebMvc注解导入的 DelegatingWebMvcConfiguration 继承自 WebMvcConfigurationSupport
所以 添加 @EnableWebMvc 后 WebMvcAutoConfiguration 自动配置就会失效
16.国际化自动配置类 MessageSourceAutoConfiguration 配置国际化资源文件
springmvc下的配置:
<!--设置国际化支持,配置国际化资源文件 id="messageSource“不能乱取名--> <bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource"> <!--setBaseNames()--> <property name="basenames"> <array> <value>i18n.logion</value> </array> </property> </bean>
springboot下的自动配置:
只有资源存在,这个国际化配置类才会生效:
所以,这里就有两种方式了:
方式一:自定义文件夹,添加 spring.messages.basename 配置
方式二: 放入指定的 messages文件夹:
这是自动配置类生效,才会为我们配置 MessageSource
17. LocaleResolver 的自动化配置
之前springmvc 对比配置
<!--设置国际化支持,配置国际化资源文件 id="messageSource“不能乱取名--> <bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource"> <!--setBaseNames()--> <property name="basenames"> <array> <value>i18n.logion</value> </array> </property> </bean> <!-- 使用SessionLocaleResolver,保持local状态,会从session中获取local对象 id="localeResolver"只能叫localeResolver,为了覆盖springmvc默认AcceptHeaderLocaleResolver 不配制的话默认使用的是 AcceptHeaderLocaleResolver,会从请求头里获取“Aceept-Language” 国际化二:SessionLocaleResolver 替换默认的 AcceptHeaderLocaleResolver --> <bean class="org.springframework.web.servlet.i18n.SessionLocaleResolver" id="localeResolver"></bean>
<!-- 不实用AcceptHeaderLocaleResolver 是因为每次请求都要判断 都要Accept-Language 为空才使用配置语言-->
<!-- <bean class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver" id="localeResolver"></bean>-->
而在 WebMvcAutoConfiguration 自动配置类里,springboot也帮我们配好了
注意:
可以通过进行配置,来选择时固定使用某一语言还是从头里去取
旧版本是这么写的,新版本已经弃用了,转为 spring.web.locale-resolver
18:
AcceptHeaderLocaleResolver局限性是每次请求都会判断 Accept-Language 。没有才会使用默认配置。所以我们之前使用
org.springframework.web.servlet.i18n.SessionLocaleResolver
所以我们还是要自定义localeResolver
19.自定义 localeResolver 查看12步的参考代码里有
20.统一异常处理自动配置,
统一配置类 ErrorMvcAutoConfiguration
BasicErrorController 下面定义的处理接口
在errorHtml ()里调用的resolveErrorView()里使用的就是 DefaultErrorAttributes
对于ajax请求的error处理,没办法更改,只能自定义类实现 AbstractErrorController 去替换 BasicErrorController 的自动配置 自己去实现 error()处理

@Controller @RequestMapping("/error") public class CustomErrorController extends AbstractErrorController { public CustomErrorController(ErrorAttributes errorAttributes, List<ErrorViewResolver> errorViewResolvers) { super(errorAttributes, errorViewResolvers); } Logger logger = LoggerFactory.getLogger(CustomErrorController.class); /** * 处理浏览器请求的 * 加上异常日志记录 * * @param request * @param response * @return */ @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions())); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); logger.error(model.get("trace").toString()); return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); } /** * 处理ajax * 修改返回类型:Result 完成 * 加上异常日志记录 * * @param request * @return */ @RequestMapping @ResponseBody public Result error(HttpServletRequest request) { HttpStatus status = getStatus(request); if (status == HttpStatus.NO_CONTENT) { return new Result(204, "No Content"); } Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions()); String code = body.get("status").toString(); String message = body.get("message").toString(); logger.error(body.get("trace").toString()); return new Result(Integer.parseInt(code), message); } /** * 异常信息的选项 * * @return */ protected ErrorAttributeOptions getErrorAttributeOptions() { ErrorAttributeOptions of = ErrorAttributeOptions.of(ErrorAttributeOptions.Include.MESSAGE, ErrorAttributeOptions.Include.STACK_TRACE, ErrorAttributeOptions.Include.EXCEPTION); return of; } @Override public String getErrorPath() { return null; } }
当然,异常处理还可以使用
@ControllerAdvice
@ExceptionHandler
这个更加灵活,在这里只为分析springboot的自动配置以及根据他的自动配置进行定制。所以这两个注解不再这里的讨论范围内
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!