日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

spring启动之xml

發(fā)布時(shí)間:2024/3/26 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring启动之xml 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本系列源碼都是基于spring-4.3.8版本之上,其他版本略有差異,但總體的核心思想相同。同時(shí),為了使貼出的源代碼盡可能的緊湊,可能會(huì)刪去一些異常捕獲、日志輸出等代碼。若文中存在紕漏錯(cuò)誤,歡迎指正。

?

如上圖ContextLoaderListener繼承自ContextLoader又實(shí)現(xiàn)了ServletContextListener,

前者用于初始化Spring容器,后者用于在web容器初始化時(shí)通知自己。

由于ContextLoaderListener實(shí)現(xiàn)了ServletContextListener,當(dāng)web容器初始化時(shí),會(huì)調(diào)用ServletContextListener#contextInitialized,開(kāi)始初始化servlet上下文監(jiān)聽(tīng)器,ContextLoaderListener就是其中一個(gè)。

public void contextInitialized(ServletContextEvent event) {initWebApplicationContext(event.getServletContext());}

而ContextLoaderListener通過(guò)調(diào)用父類ContextLoader#initWebApplicationContext方法展開(kāi)了Spring初始化之路。

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {// 當(dāng)前servletContext若已存在上下文,則說(shuō)明已開(kāi)始啟動(dòng),則拋出異常,終止spring容器啟動(dòng)if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {throw new IllegalStateException("Cannot initialize context because there is already a root application context present - " +"check whether you have multiple ContextLoader* definitions in your web.xml!");}// 判斷當(dāng)前上下文是否存在,不存在,則進(jìn)行創(chuàng)建if (this.context == null) {this.context = createWebApplicationContext(servletContext);}// 若沒(méi)有進(jìn)行過(guò)特殊配置,那么該context的類型默認(rèn)為XmlWebApplicationContext,具體可見(jiàn)createWebApplicationContext// 且context的類型必然是ConfigurableWebApplicationContext的子類if (this.context instanceof ConfigurableWebApplicationContext) {ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;if (!cwac.isActive()) {if (cwac.getParent() == null) {ApplicationContext parent = loadParentContext(servletContext);cwac.setParent(parent);}// 該方法為spring容器真正的初始化入口configureAndRefreshWebApplicationContext(cwac, servletContext);}}// 將上下文設(shè)置到servletContext中,用于給其他容器獲取,如SpringMvc的初始化Servlet就是通過(guò)該方法獲取到父容器的servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);ClassLoader ccl = Thread.currentThread().getContextClassLoader();if (ccl == ContextLoader.class.getClassLoader()) {currentContext = this.context;}else if (ccl != null) {currentContextPerThread.put(ccl, this.context);}return this.context;} protected WebApplicationContext createWebApplicationContext(ServletContext sc) {// 創(chuàng)建context的第一步,即需要確定該context的類型Class<?> contextClass = determineContextClass(sc);// 不論其最終是何類型,其必須實(shí)現(xiàn)ConfigurableWebApplicationContext接口,否則直接拋出異常if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Custom context class [" + contextClass.getName() +"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");}return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);} protected Class<?> determineContextClass(ServletContext servletContext) {// 默認(rèn)從servletContext中獲取初始化參數(shù),即我們web.xml中可配置的contextClass中獲取類的全限定名String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);if (contextClassName != null) {try {return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());}catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", ex);}}else {// 若沒(méi)有獲取到,則會(huì)以默認(rèn)的策略,從本類的同級(jí)目錄下以WebApplicationContext全限定名為key讀取ContextLoader.properties的配置// 最終獲取到的即org.springframework.web.context.support.XmlWebApplicationContextcontextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());try {return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());}catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", ex);}}} protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {if (ObjectUtils.identityToString(wac).equals(wac.getId())) {// 從web.xml中獲取初始化參數(shù)contextId,作為當(dāng)前容器的唯一IDString idParam = sc.getInitParameter(CONTEXT_ID_PARAM);if (idParam != null) {wac.setId(idParam);}else {wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +ObjectUtils.getDisplayString(sc.getContextPath()));}}// 將當(dāng)前ServletContext設(shè)置到當(dāng)前容器中wac.setServletContext(sc);// 從web.xml中讀取初始化參數(shù)contextConfigLocation,讀取出的配置文件路徑稍后將逐個(gè)加載String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);if (configLocationParam != null) {// 將配置文件路徑設(shè)置到本容器中wac.setConfigLocation(configLocationParam);}ConfigurableEnvironment env = wac.getEnvironment();if (env instanceof ConfigurableWebEnvironment) {((ConfigurableWebEnvironment) env).initPropertySources(sc, null);}// 個(gè)性化啟動(dòng)上下文customizeContext(sc, wac);/*** 容器加載的核心方法,* 不論是以注解方式啟動(dòng)的AnnotationConfigWebApplicationContext* 還是spring-boot的啟動(dòng)類SpringApplication* 最終都需要調(diào)用該方法,即AbstractApplicationContext#refresh*/wac.refresh();} protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {/*** 決定上下文需要初始化的類* 從<init-param>中獲取"globalInitializerClasses"、"contextInitializerClasses"*/List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =determineContextInitializerClasses(sc);for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) {Class<?> initializerContextClass =GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);if (initializerContextClass != null && !initializerContextClass.isInstance(wac)) {throw new ApplicationContextException(String.format("Could not apply context initializer [%s] since its generic parameter [%s] " +"is not assignable from the type of application context used by this " +"context loader: [%s]", initializerClass.getName(), initializerContextClass.getName(),wac.getClass().getName()));}this.contextInitializers.add(BeanUtils.instantiateClass(initializerClass));}// 排序并逐個(gè)初始化ApplicationContextInitializerAnnotationAwareOrderComparator.sort(this.contextInitializers);for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {initializer.initialize(wac);}}

由于AbstractApplicationContext#refresh方法太長(zhǎng),限于本篇篇幅,該方法的細(xì)節(jié)將在之后進(jìn)行源碼分析。

總結(jié)

以上是生活随笔為你收集整理的spring启动之xml的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 在线免费观看黄色av | 岛国片免费在线观看 | 日韩怡春院 | 特级a级片| 亚洲午夜精品久久久久久人妖 | 精品久久久久久无码国产 | 驯服少爷漫画免费观看下拉式漫画 | 麻豆av电影网 | 欧美在线视频一区二区三区 | 日本高清视频一区二区 | 黄色一级网 | 在线观看的av | 国产又粗又硬 | 岛国av一区二区 | 性高潮视频在线观看 | 看免费一级片 | 国产在成人精品线拍偷自揄拍 | 欧美国产日韩一区二区三区 | 永久av网站 | 欧美特一级片 | 国产一级视频免费观看 | 免费在线激情视频 | 久久久精品免费 | 国产免费视屏 | 67194在线免费观看 | 美女露隐私网站 | 成人福利视频在线观看 | 小视频在线观看 | 日本精品二区 | 欧美日韩成人一区二区在线观看 | 中国女人内谢69xxxx免费视频 | 日韩一级片免费观看 | 国产一区色| 一区二区国产精品视频 | 高清中文字幕 | 日韩av日韩 | 亚洲国产无码精品 | 欧美日韩高清一区二区 国产亚洲免费看 | 97超碰色 | 亚洲成人三区 | 色香欲综合网 | 国产又粗又黄的视频 | 91视频h | 国产黄片毛片 | 日韩av二区| 涩涩涩涩涩涩涩涩涩涩 | 亚洲天堂伊人网 | 性少妇videosexfreexxx片 | 伦理自拍 | 亚洲天堂久久新 | 亚洲第一淫片 | 亚洲av成人一区二区国产精品 | 人人妻人人藻人人爽欧美一区 | 免费吃奶摸下激烈视频 | 久久韩日 | 国产乱妇无码大片在线观看 | 日本一区二区不卡在线观看 | 日韩中文字幕影院 | 美女四肢被绑在床扒衣 | 18禁网站免费无遮挡无码中文 | 麻豆成人精品国产免费 | 日韩精品视频一区二区在线观看 | 国产精品久久久久久久久绿色 | 欧美人交a欧美精品 | 欧美性猛交ⅹ乱大交3 | 欧美永久精品 | 人妻va精品va欧美va | 伊人久久国产精品 | 色窝窝无码一区二区三区 | 中文字幕乱码无码人妻系列蜜桃 | 操小妞| 欧美亚洲另类视频 | 不卡一区二区在线观看 | 极品销魂美女一区二区三区 | 殴美一级黄色片 | 成人视屏在线 | 国产精品夜夜嗨 | 91天天干 | 久热这里只有 | 欧美黄色精品 | 天天爽影院 | 美女搡bbb又爽又猛又黄www | 玖玖精品| 亚洲热在线 | 97超碰人人草 | 乖女从小调教h尿便器小说 欧美韩一区二区 | 91网国产| 中文字幕av高清 | 亚洲一区二区三区婷婷 | 午夜激情视频在线 | 特级大胆西西4444人体 | 人人人妻人人澡人人爽欧美一区 | 亚洲精品男人的天堂 | 日日嗨av一区二区三区四区 | 我要爱爱网 | 美女被草出白浆 | 永久免费成人代码 | 精品人妻一区二区三区在线视频 | 成人资源站|