最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

女朋友要我講解@Controller注解的原理,真是難為我了

2023-07-17 00:01 作者:火星上的彩虹美不美  | 我要投稿

背景

女朋友被公司裁員一個月了,和我一樣作為后端工程師,最近一直在找工作,面試了很多家還是沒有找到工作,面試官問@Controller的原理,她表示一臉懵,希望我能給她講清楚。之前我也沒有好好整理這塊知識,這次借助這個機(jī)會把它徹底搞清楚。

我們知道Controller注解的類能夠?qū)崿F(xiàn)接收并處理Http請求,其實(shí)在我看Spring mvc模塊的源碼之前也和我女朋友目前的狀態(tài)一樣,很疑惑,Spring框架是底層是如何實(shí)現(xiàn)的,通過使用Controller注解就簡單的完成了http請求的接收與處理。

有疑問就好啊,因?yàn)榕d趣是最好的老師,如果有興趣才有動力去弄懂這個技術(shù)點(diǎn)。

看過前面的文章的同學(xué)就會知道,學(xué)習(xí)Spring的所有組件,腦袋里要有一個思路,那就是解析組件和運(yùn)用組件兩個流程,這是Spring團(tuán)隊(duì)實(shí)現(xiàn)組件的統(tǒng)一套路,大家可以回憶一下是不是這么回事。

一、Spring解析Controller注解

首先我們看看Spring是如何解析Controller注解的,打開源碼看看他長啥樣??

java復(fù)制代碼@Target({ElementType.TYPE}) @Component public @interface Controller { ?? String value() default ""; }

發(fā)現(xiàn)Controller注解打上了Component的注解,這樣Spring做類掃描的時候,發(fā)現(xiàn)了@Controller標(biāo)記的類也會當(dāng)作Bean解析并注冊到Spring容器。 我們可以看到Spring的類掃描器,第一個就注冊了Component注解的掃描

java復(fù)制代碼//org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider protected void registerDefaultFilters() { ?? this.includeFilters.add(new AnnotationTypeFilter(Component.class)); }

這樣Spring容器啟動完成之后,bean容器中就有了被Controller注解標(biāo)記的bean實(shí)例了。 到這里只是單純的把Controller標(biāo)注的類實(shí)例化注冊到Spring容器,和Http請求接收處理沒半毛錢關(guān)系,那么他們是怎么關(guān)聯(lián)起來的呢?

二、Spring解析Controller注解標(biāo)注的類方法

這個時候Springmvc組件中的另外一個組件就閃亮登場了

RequestMappingHandlerMapping

RequestMappingHandlerMapping 看這個名就可以知道他的意思,請求映射處理映射器。 這里就是重點(diǎn)了,該類間接實(shí)現(xiàn)了InitializingBean方法,bean初始化后執(zhí)行回調(diào)afterPropertiesSet方法,里面調(diào)用initHandlerMethods方法進(jìn)行初始化handlermapping。

java復(fù)制代碼 //類有沒有加Controller的注解 protected boolean isHandler(Class<?> beanType) { ?? return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || ?? ? ? ? AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class)); } ?protected void initHandlerMethods() { ?? //所有的bean ?? String[] beanNames= applicationContext().getBeanNamesForType(Object.class); ? ? for (String beanName : beanNames) { ?? ? ? ? Class<?> beanType = obtainApplicationContext().getType(beanName); ?? ? ? ? //有Controller注解的bean ?? ? ? ? if (beanType != null && isHandler(beanType)) { ?? ? ? ? ? ?detectHandlerMethods(beanName); ?? ? ? ? } ?? } ?? handlerMethodsInitialized(getHandlerMethods()); }

這里把標(biāo)注了Controller注解的實(shí)例全部找到了,然后調(diào)用detectHandlerMethods方法,檢測handler方法,也就是解析Controller標(biāo)注類的方法。

java復(fù)制代碼 private final Map<T, MappingRegistration<T>> registry = new HashMap<>(); ?protected void detectHandlerMethods(final Object handler) { ?? Class<?> handlerType = (handler instanceof String ? ?? ? ? ? obtainApplicationContext().getType((String) handler) : handler.getClass()); ? ? if (handlerType != null) { ?? ? ?final Class<?> userType = ClassUtils.getUserClass(handlerType); ?? ? ?//查找Controller的方法 ?? ? ?Map<Method, T> methods = MethodIntrospector.selectMethods(userType, ?? ? ? ? ? ?(MethodIntrospector.MetadataLookup<T>) method -> getMappingForMethod(method, userType)); ? methods.forEach((method, mapping) -> { //注冊 ? ? ? ? ? ? ? ? ?this.registry.put(mapping,new MappingRegistration<>(mapping,method)); ? ?? ? ?}); ?? } ?

到這里為止,Spring將Controller標(biāo)注的類和類方法已經(jīng)解析完成?,F(xiàn)在再來看RequestMappingHandlerMapping這個類的作用,他就是用來注冊所有Controller類的方法。

三、Spring調(diào)用Controller注解標(biāo)注的方法

接著還有一個重要的組件RequestMappingHandlerAdapter 它就是用來將請求轉(zhuǎn)換成HandlerMethod,并且完成請求處理的流程。 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

java復(fù)制代碼@Override public boolean supports(Object handler) { ?? return handler instanceof HandlerMethod; } ?protected ModelAndView handleInternal(HttpServletRequest request, ?? ? ?HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ?? //請求check ?? checkRequest(request); ?? //調(diào)用handler方法 ?? mav = invokeHandlerMethod(request, response, handlerMethod); ?? //返回 ?? return mav; }

看到這里,就知道http請求是如何被處理的了,我們找到DispatcherServlet的doDispatch方法看看,確實(shí)是如此??!

四、DispatcherServlet調(diào)度Controller方法完成http請求

java復(fù)制代碼protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { ?? ? ? ? // 從注冊表查找handler ?? ? ? ? HandlerExecutionChain mappedHandler = getHandler(request); ?? ? ? ? HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); ?? ? ? ? // 調(diào)用 ?? ? ? ? ModelAndView m = ha.handle(processedRequest, response, mappedHandler.getHandler()); ?? ? ? ? // ? ? ? ? ? processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); }

DispatcherServlet是Spring mvc的總?cè)肟?,看到doDispatch方法后,全部都聯(lián)系起來了。。。 最后我們看看http請求在Spring mvc中的流轉(zhuǎn)流程。

第一次總結(jié)SpringMvc模塊,理解不到位的麻煩各位大佬指正。

女朋友要我講解@Controller注解的原理,真是難為我了的評論 (共 條)

分享到微博請遵守國家法律
安乡县| 东乌| 道真| 肃南| 苍溪县| 咸丰县| 菏泽市| 汉川市| 牙克石市| 广州市| 汝阳县| 广灵县| 金塔县| 保靖县| 白山市| 当雄县| 东阳市| 墨竹工卡县| 烟台市| 策勒县| 平和县| 乌鲁木齐县| 安陆市| 延边| 阜阳市| 麻栗坡县| 通化县| 兴城市| 博罗县| 凤台县| 武定县| 体育| 玉环县| 社旗县| 谢通门县| 江孜县| 大化| 庄河市| 宿松县| 张家口市| 新密市|