
本文介绍springmvc被springboot整合之后,web容器注册spring容器,初始化DispatcherServlet,controller里面的方法注册,访问过程。
首先从springboot-autoconfigure包下面的meta-INF/spring-factories里面找到WebMvcAutoConfiguration这个自动配置类,在209行会看到RequestMappingHandlerMapping这个类被创建成bean,这个类有个afterPropertiesSet()方法,在spring容器初始化就会调用这个方法,这个方法用来处理所有标记有@controller的注解的类,并找出所有标记@RequestMapping注解的方法,存到HandlerMethod类里。等第一次访问时就走DispathServlet的init初始化流程
注册类
部分代码
在spring-factories文件里会找到DispatcherServletAutoConfiguration和WebMvcAutoConfiguration,其他的类那你也可以自己打开看看,断点调试。
spring.factories文件中部分代码 org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,
进入DispatcherServletAutoConfiguration类打断点可以看到图,这里会注册一个dispatchServlet,拦截路径是 / 。后面访问的时候会进入初始化方法init()。
断点进入AbstractHandlerMethodMapping类
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
// 获取spring容器中所有的bean,进行处理
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
//处理bean的方法,会进行过滤
processCandidateBean(beanName);
}
}
// 空方法
handlerMethodsInitialized(getHandlerMethods());
}
看截图
这里会进入发现处理的方法。看判断的isHandler(beanType)这个方法,这里进行过滤
@Override
protected boolean isHandler(Class> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
protected void detectHandlerMethods(Object handler) {
Class> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
Class> userType = ClassUtils.getUserClass(handlerType);
Map methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.metadataLookup) method -> {
try {
//找到所有的方法,可以进入这里看看
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
else if (mappingsLogger.isDebugEnabled()) {
mappingsLogger.debug(formatMappings(userType, methods));
}
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// 注册方法到map中
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
注册方法AbstractHandlerMethodMapping这个类中
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
注册
public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
// 创建方法类
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
//校验是否已经存在
validateMethodMapping(handlerMethod, mapping);
Set directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping);
for (String path : directPaths) {
this.pathLookup.add(path, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
corsConfig.validateAllowCredentials();
this.corsLookup.put(handlerMethod, corsConfig);
}
// 注册到map中,以后拿处理器映射器从这里找
this.registry.put(mapping,
new MappingRegistration<>(mapping, handlerMethod, directPaths, name, corsConfig != null));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
页面访问任意路径:
后续补齐
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)