zl程序教程

您现在的位置是:首页 >  后端

当前栏目

SpringMVC 遗漏补充

SpringMVC 补充
2023-09-27 14:21:20 时间
说到SpringMVC,一般都说Spring将请求与方法进行了映射,所以每次请求都能找到对应的方法,这次我想找到代码层面上是如何处理的,而不是泛泛而谈。我们在springmvc启动的时候说到,由于DispatcherServlet 实现了Servlet,因此会默认实现其init( )方法.

说到SpringMVC,一般都说Spring将请求与方法进行了映射,所以每次请求都能找到对应的方法,这次我想找到代码层面上是如何处理的,而不是泛泛而谈。我们在springmvc启动的时候说到,由于DispatcherServlet 实现了Servlet,因此会默认实现其init方法,在init方法中找到了我比较感兴趣的两个函数
(1) initHandlerMappings(context)
(2) initHandlerAdapters(context)

这两个函数的内部实现不贴代码了,就是将一些默认的类经常初始化到容器,供请求过来的时候进行调用。ok,这是我前几次看完代码得到的感悟,当时始终没有解决我的一个疑问,到底在什么时候将URL与方法进行了映射?通过Debug跟踪请求也是莫名其妙的Map里面就存在了映射关系,实在没有办法只能反向查找,终于在 AbstractHandlerMethodMapping 这个类中找到了答案。

public abstract class AbstractHandlerMethodMapping T 

 extends AbstractHandlerMapping implements InitializingBean

AbstractHandlerMethodMapping 是SpringMVC默认的一个Handler,由于其实现了InitializingBean的接口,那么在容器启动的时候就会调用:

@Override

public void afterPropertiesSet() {

 initHandlerMethods();

}

step1:

 BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class)

 扫描引用上下文,获取所有的Bean

step2:

 Class ? beanType = getApplicationContext().getType(beanName);

 protected boolean isHandler(Class ? beanType) {

 return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||

 AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));

遍历所有的Bean,筛选拥有注解Controller 或者 RequestMapping的类

step3:

 进入最主要的函数体:detectHandlerMethods
protected void detectHandlerMethods(final Object handler) {

 // 获取handler类型

 Class ? handlerType = (handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());

 final Class ? userType = ClassUtils.getUserClass(handlerType);

 // 从实体类中获取方法(一般都是controller类) 

 // 这边有兴趣的话可以关注一下selectMethods的实现,应该会在工作中会有涉及到

 // 使用反射的方式获所有的方法

 Map Method, T methods = MethodIntrospector.selectMethods(userType,

 new MethodIntrospector.MetadataLookup T () {

 @Override

 public T inspect(Method method) {

 return getMappingForMethod(method, userType);

 for (Map.Entry Method, T entry : methods.entrySet()) {

 Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType);

 T mapping = entry.getValue();

 // 将其映射关系放入到一个对象里面

 registerHandlerMethod(handler, invocableMethod, mapping);

}

大致就是这样的一个过程,感觉像是记录的一个流水账,哈哈

补充:

 HandlerMappings在DispatcherServlet的主要作用就是为请求匹配对应的Controller,建议一个映射关系,根据请求查找Handler,Interceptor。HandlerMappings将请求传递到HandlerExecutionChain中,HandlerExecutionChain包含了一个能处理该请求的处理器,已经需要的拦截器。

 DispatcherServlet在没有配置处理器的情况下,会默认的从 DispatcherServlet.properties 配置文件中初始化类:BeanNameUrlHandlerMapping/DefaultAnnotationHandlerMapping

 AbstractHandlerMapping是接口HandlerMappings的抽象实现,是所有的HandlerMapping实现类的父类,其作用是初始化拦截器,将拦截器放入到adaptedInterceptors中,在请求过来的时候,调用getHandlerExecutionChain方法,会遍历这个adaptedInterceptors集合,选择匹配的拦截器。

千万别再卷Spring循环依赖了,这篇文章一定让你搞清楚 4.1 满足循环依赖的条件是什么? 必须是单例模式 循环依赖类,必须能实例化(空构造,或构造参数满足循环依赖条件) 4.2 循环依赖可能导致什么问题? 在执行初始化的时候,如果初始化方法,依赖循环来的属性注入参数,可能导致获取不到数据信息的情况如上面问题1。 4.3 为什么要用三级缓存而不是二级缓存? 为了满足Spring声明周期方法,即对半成品的B进行提前生命周期处理。如实现AOP.
还在为处理事务烦恼吗,要不试试Spring是如何处理业务的 Spring 框架不局限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。
Spring 是如何解决循环依赖的?写得太好了 做 Java 开发的,一般都绕不开 Spring,那么面试中肯定会被问到 Spring 的相关内容,而循环依赖又是 Spring 中的高频面试题。 这不前段时间,我的一朋友去面试,就被问到了循环依赖,结果他还在上面还小磕了一下,他们聊天过程如下 面试官:说下什么是循环依赖