Spring WebMVC初始化Controller流程详解

网友投稿 465 2022-08-26


Spring WebMVC初始化Controller流程详解

目录SpringWebMVC初始化Controller流程获取容器初始化的所有beanName(父子容器概念)获取所有声明为Controller类的beanName开始处理这种类型的beanName@Controller类中初始化问题第一种方法第二种方法

Spring WebMVC初始化Controller流程

此篇文章开始之前先向大家介绍一个接口 InitializingBean

这个接口的作用如果了解spring生命周期的应该知道 ,这个接口的作用就是在bean初始化之后会执行的init方法

public interface InitializingBean {

void afterPropertiesSet() throws Exception;

}

当然能实现这种方式的方法spring还介绍了关于注解的@PostConstruct 和xml 的 init-method = "" 的两种方式。但是springmvc使用的是接口的方式。

这里要介绍的初始化Controller是指填充完HandlerMapping map即代表初始化Controller流程

我们再提一点小知识。声明一个controller类有哪些方式。(现在应该没有人用第二/三种方式吧)

1.使用注解@Controller 和 PjGJOPpyNn请求路径@RequestMapping2.实现 Controller 接口 并将该类交给spring容器管理beanName为请求路径3.实现 HttpRequestHandler 接口并将该类交给spring容器管理beanName为请求路径

那么我们的map填充就从实现了InitializingBean 接口 的afterPropertiesSet这个方法开始。

源码中是这个类 AbstractHandlerMethodMapping(下面的代码有删减)

public void afterPropertiesSet() {

this.initHandlerMethods();

}

protected void initHandlerMethods() {

String[] var1 = this.getCandidateBeanNames();//1.获取容器初始化的所有beanName

int var2 = var1.length;

for(int var3 = 0; var3 < var2; ++var3) {

String beanName = var1[var3];

if (!beanName.startsWith("scopedTarget.")) {

this.prochttp://essCandidateBean(beanName);//2.获取所有声明为Controller类的beanName

}

}

this.handlerMethodsInitialized(this.getHandlerMethods());

}

获取容器初始化的所有beanName(父子容器概念)

protected String[] getCandidateBeanNames() {

return this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.obtainApplicationContext(), Object.class) : this.obtainApplicationContext().getBeanNamesForType(Object.class);

}

获取所有声明为Controller类的beanName

protected void processCandidateBean(String beanName) {

Class beanType = null;

try {

beanType = this.obtainApplicationContext().getType(beanName);//获取bean的类型

} catch (Throwable var4) {

if (this.logger.isTraceEnabled()) {

this.logger.trace("Could not resolve type for bean '" + beanName + "'", var4);

}

}

if (beanType != null && this.isHandler(beanType)) {//获取所有声明为Controller类的beanName

this.detectHandlerMethods(beanName);//1.开始处理这种类型的beanName

}

}

开始处理这种类型的beanName

protected void detectHandlerMethods(Object handler) {

Class> handlerType = handler instanceof String ? this.obtainApplicationContext().getType((String)handler) : handler.getClass();

if (handlerType != null) {

Class> userType = ClassUtils.getUserClass(handlerType);

Map methods = MethodIntrospector.selectMethods(userType, (method) -> {

try {

return this.getMappingForMethod(method, userType);//1.获取到类类型下所有的方法

} catch (Throwable var4) {

throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, var4);

}

});

if (this.loggehttp://r.isTraceEnabled()) {

this.logger.trace(this.formatMappings(userType, methods));

}

methods.forEach((method, mapping) -> {

Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);

this.registerHandlerMethod(handler, invocableMethod, mapping);//注册并填充map

});

}

}

获取到类类型下所有的方法和注册并填充map

第一个 MultiValueMap urlLookup = new LinkedMultiValueMap();

urlLookup.add(url, mapping);

eg:url = '/test/test.do'

mapping是一个RequestMappingInfo 对象 RequestMappingInfo.patternsCondition = T --> /test/test.do

第二个 Map> registry = new HashMap();

eg:key = 'url' value = 'method'

而我们的第二种和第三种的方式基本没有用了,因为会出现类爆炸,就像原始的servlet一样每一个方法都需要写一个类。

这两种方式是通过beanName为路径来实例化对象并执行通过该对象来执行里面的方法的。

源码中这两种map的填充方式是在bean的生命周期中通过实现beanFactory的applyBeanPostProcessorsBeforeInitialization方法来填充的。

@Controller 类中初始化问题

在Controller类中常常遇到有些参数需要初始化,甚至有些只允许初始化一次,而Controller类不像servelet类可以调用init()函数进行初始化,这里想到的办法是设置标记值,让初始化部分只调用一次。

第一种方法

设置isStart值。

private static Boolean isStart = false;

if(!isStart){

  //进行初始化

  isStart=true;

}

第二种方法

使用注释@PostConstruct,该注释的类会在类初始化时进行调用。

@PostConstruct

private void init(){

//进行初始化

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:python requests模块获取jfrog artifactory发版的版本号(python是干什么的)
下一篇:python将1970开始的时间戳转换为标准时间(python日期转换为时间戳)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~