SpringMVC源码-@ControllerAdvice和 @InitBinder注解源码讲解

news/2024/10/18 17:14:49/

1.@ControllerAdvice修饰的类何时被加载扫描

被@ControllerAdvice修饰的类是作用于全局的
initStrategies 初始化springmvc的9大组件

java">initStrategies:531, DispatcherServlet (org.springframework.web.servlet)
onRefresh:514, DispatcherServlet (org.springframework.web.servlet)
onApplicationEvent:901, FrameworkServlet (org.springframework.web.servlet)
onApplicationEvent:1277, FrameworkServlet$ContextRefreshListener (org.springframework.web.servlet)
onApplicationEvent:1273, FrameworkServlet$ContextRefreshListener (org.springframework.web.servlet)
onApplicationEvent:64, GenericApplicationListenerAdapter (org.springframework.context.event)
onApplicationEventInternal:109, SourceFilteringListener (org.springframework.context.event)
onApplicationEvent:73, SourceFilteringListener (org.springframework.context.event)
doInvokeListener:215, SimpleApplicationEventMulticaster (org.springframework.context.event)
invokeListener:202, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:164, SimpleApplicationEventMulticaster (org.springframework.context.event)
publishEvent:440, AbstractApplicationContext (org.springframework.context.support)
publishEvent:379, AbstractApplicationContext (org.springframework.context.support)
finishRefresh:1053, AbstractApplicationContext (org.springframework.context.support)
refresh:618, AbstractApplicationContext (org.springframework.context.support)
configureAndRefreshWebApplicationContext:759, FrameworkServlet (org.springframework.web.servlet)
createWebApplicationContext:715, FrameworkServlet (org.springframework.web.servlet)
createWebApplicationContext:773, FrameworkServlet (org.springframework.web.servlet)
initWebApplicationContext:625, FrameworkServlet (org.springframework.web.servlet)
initServletBean:536, FrameworkServlet (org.springframework.web.servlet)
init:185, HttpServletBean (org.springframework.web.servlet)
init:158, GenericServlet (javax.servlet)
initServlet:1164, StandardWrapper (org.apache.catalina.core)
loadServlet:1117, StandardWrapper (org.apache.catalina.core)
load:1010, StandardWrapper (org.apache.catalina.core)
loadOnStartup:4957, StandardContext (org.apache.catalina.core)
startInternal:5264, StandardContext (org.apache.catalina.core)
start:183, LifecycleBase (org.apache.catalina.util)
addChildInternal:726, ContainerBase (org.apache.catalina.core)
addChild:698, ContainerBase (org.apache.catalina.core)
addChild:696, StandardHost (org.apache.catalina.core)
manageApp:1783, HostConfig (org.apache.catalina.startup)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:293, BaseModelMBean (org.apache.tomcat.util.modeler)
invoke:819, DefaultMBeanServerInterceptor (com.sun.jmx.interceptor)
invoke:801, JmxMBeanServer (com.sun.jmx.mbeanserver)
createStandardContext:460, MBeanFactory (org.apache.catalina.mbeans)
createStandardContext:408, MBeanFactory (org.apache.catalina.mbeans)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:293, BaseModelMBean (org.apache.tomcat.util.modeler)
invoke:819, DefaultMBeanServerInterceptor (com.sun.jmx.interceptor)
invoke:801, JmxMBeanServer (com.sun.jmx.mbeanserver)
invoke:468, MBeanServerAccessController (com.sun.jmx.remote.security)
doOperation:1468, RMIConnectionImpl (javax.management.remote.rmi)
access$300:76, RMIConnectionImpl (javax.management.remote.rmi)
run:1309, RMIConnectionImpl$PrivilegedOperation (javax.management.remote.rmi)
doPrivileged:-1, AccessController (java.security)
doPrivilegedOperation:1408, RMIConnectionImpl (javax.management.remote.rmi)
invoke:829, RMIConnectionImpl (javax.management.remote.rmi)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
dispatch:346, UnicastServerRef (sun.rmi.server)
run:200, Transport$1 (sun.rmi.transport)
run:197, Transport$1 (sun.rmi.transport)
doPrivileged:-1, AccessController (java.security)
serviceCall:196, Transport (sun.rmi.transport)
handleMessages:568, TCPTransport (sun.rmi.transport.tcp)
run0:826, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
lambda$run$0:683, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
run:-1, 1659438018 (sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$24)
doPrivileged:-1, AccessController (java.security)
run:682, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
runWorker:1142, ThreadPoolExecutor (java.util.concurrent)
run:617, ThreadPoolExecutor$Worker (java.util.concurrent)
run:748, Thread (java.lang)

initHandlerAdapters(context); 初始化 HandlerAdapter:处理适配器,主要包含Http请求处理器适配器,简单控制器处理器适配器,注解方法处理器适配器

在这里插入图片描述
循环遍历生成,遍历到RequestMappingHandlerAdapter,类图如下:
在这里插入图片描述
因为实现了InitializingBean接口,当初始化调用afterPropertiesSet方法:
在这里插入图片描述
initControllerAdviceCache 初始化注释了@ControllerAdvice的类的相关属性

java">	private void initControllerAdviceCache() {// 判断当前应用程序上下文是否为空,如果为空,直接返回if (getApplicationContext() == null) {return;}// 扫描@ControllerAdvice注解的Bean,生成对应的ControllerAdviceBean对象,并将进行排序List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();// 遍历ControllerAdviceBean数组for (ControllerAdviceBean adviceBean : adviceBeans) {Class<?> beanType = adviceBean.getBeanType();if (beanType == null) {throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);}// 扫描有`@ModelAttribute`,无`@RequestMapping`注解的方法,添加到`modelAttributeAdviceCache`属性中// 该类方法用于在执行方法前修改 Model 对象Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);if (!attrMethods.isEmpty()) {this.modelAttributeAdviceCache.put(adviceBean, attrMethods);}// 扫描有`@InitBinder`注解的方法,添加到`initBinderAdviceCache`属性中// 该类方法用于在执行方法前初始化数据绑定器Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);if (!binderMethods.isEmpty()) {this.initBinderAdviceCache.put(adviceBean, binderMethods);}// 如果是RequestBodyAdvice或ResponseBodyAdvice的子类,添加到requestResponseBodyAdviceBeans中if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {requestResponseBodyAdviceBeans.add(adviceBean);}}// 将requestResponseBodyAdviceBeans添加到this.requestResponseBodyAdvice属性中if (!requestResponseBodyAdviceBeans.isEmpty()) {this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);}// 打印日志if (logger.isDebugEnabled()) {int modelSize = this.modelAttributeAdviceCache.size();int binderSize = this.initBinderAdviceCache.size();int reqCount = getBodyAdviceCount(RequestBodyAdvice.class);int resCount = getBodyAdviceCount(ResponseBodyAdvice.class);if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) {logger.debug("ControllerAdvice beans: none");}else {logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize +" @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice");}}}

List adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());

java">	/**在给定的{@link ApplicationContext}中找到带有{@link ControllerAdvice @ControllerAdvice}注释的bean* Find beans annotated with {@link ControllerAdvice @ControllerAdvice} in the* given {@link ApplicationContext} and wrap them as {@code ControllerAdviceBean}* instances.并将它们包装为{@code ControllerAdviceBean}实例。* <p>As of Spring Framework 5.2, the {@code ControllerAdviceBean} instances* in the returned list are sorted using {@link OrderComparator#sort(List)}. ,<p>从Spring Framework 5.2开始,返回列表中的{@code ControllerAdviceBean}实例使用{@link OrderComparatorsort(list)}进行排序。* @see #getOrder() * @see OrderComparator* @see Ordered*/public static List<ControllerAdviceBean> findAnnotatedBeans(ApplicationContext context) {List<ControllerAdviceBean> adviceBeans = new ArrayList<>();for (String name : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, Object.class)) {if (!ScopedProxyUtils.isScopedTarget(name)) {ControllerAdvice controllerAdvice = context.findAnnotationOnBean(name, ControllerAdvice.class);if (controllerAdvice != null) {// Use the @ControllerAdvice annotation found by findAnnotationOnBean()// in order to avoid a subsequent lookup of the same annotation.adviceBeans.add(new ControllerAdviceBean(name, context, controllerAdvice));}}}OrderComparator.sort(adviceBeans);return adviceBeans;}

该类在这里会被扫描识别类下的方法:

在这里插入图片描述
ControllerAdviceController该类会被识别到,结果如下:
在这里插入图片描述
和上面注解修饰的方法对应。


http://www.ppmy.cn/news/1538833.html

相关文章

《深度学习》OpenCV 物体跟踪 原理及案例解析

目录 一、物体跟踪 1、什么是物体跟踪 2、步骤 1&#xff09;选择跟踪算法 2&#xff09;初始化跟踪器 3&#xff09;在每个视频帧上执行跟踪 4&#xff09;可选的重新初始化 3、原理 二、案例实现 1、完整代码 1&#xff09;使用方式 2&#xff09;运行结果 2、关…

C++从入门到起飞之——(multi)set与(multi)map的的使用 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1. 序列式容器和关联式容器 2. set系列的使⽤ 2.1 set和multiset参考⽂档 2.2 set类的介绍 2.3 se…

专题:贪心算法(已完结)

1.分发饼干 方法一&#xff1a;用最大的胃口 找到最大的饼干&#xff08;先遍历胃口&#xff09; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {// 主要思路 用最大的饼干找最大的胃口sort(g.begin(),g.end());so…

双目视觉搭配YOLO实现3D测量

一、简介 双目&#xff08;Stereo Vision&#xff09;技术是一种利用两个相机来模拟人眼视觉的技术。通过对两个相机获取到的图像进行分析和匹配&#xff0c;可以计算出物体的深度信息。双目技术可以实现物体的三维重建、距离测量、运动分析等应用。 双目技术的原理是通过两…

VMware免安装直接使用Win7成品虚拟机

VMware17 pro免安装直接使用Win7成品虚拟机 下载文件 下载VMWare与win7成品虚拟机&#xff08;PS&#xff1a;里面有Win10 和Win11&#xff0c;使用方法都是一样的&#xff09; ⏬下载链接⏬ 下载链接 使用虚拟机打开成品虚拟机

《机器学习与神经网络:跨学科的突破与未来展望》

机器学习与神经网络的发展前景 一、引言 随着科技的飞速发展&#xff0c;机器学习和神经网络已经崛起&#xff0c;成为当今时代最具变革性的技术之一。这些技术不仅在学术界引起了广泛关注&#xff0c;更在实际应用中展现出惊人的潜力和价值。近日&#xff0c;2024年诺贝尔物…

扩展字段笔记

文章目录 原始方式&#xff0c;表添加字段进化方式一进化方式二动态扩展字段缺点 扩展字段的场景在实际中非常多。 原始方式&#xff0c;表添加字段 表一开始时有10个字段&#xff0c;后来因为业务需要&#xff0c;增加两个字段。 这时候实体类&#xff0c;mapper.xml都需要变…

Mac电脑SourceTree git账号密码更改提示再次输入密码

前言&#xff1a; 最近小编git账号密码修改了&#xff0c;之前在sourceTree的git仓库在拉代码提交代码就会报错&#xff0c;提示因为密码导致的仓库连接失败。 解决方案 1.在mac电脑应用程序中搜索“钥匙串” 点击钥匙串访问 在钥匙串中选登录&#xff0c;在在右侧列表中找…