spring源代碼解析二_第1頁
spring源代碼解析二_第2頁
spring源代碼解析二_第3頁
spring源代碼解析二_第4頁
spring源代碼解析二_第5頁
已閱讀5頁,還剩24頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Spring 源代碼解析(二 :ioc 容器在Web 容器中的啟動2009-08-11 (周二 10:52 Spring Spring 被圍觀一共有 900 個打醬油的路過+ 上面我們分析了IOC 容器本身的實現(xiàn),下面我們看看在典型的web 環(huán)境中,Spring IOC容器是怎樣被載入和起作用的。簡單的說,在web 容器中,通過ServletContext 為Spring 的IOC 容器提供宿主環(huán)境,對應(yīng)的建立起一個IOC 容器的體系。其中,首先需要建立的是根上下文,這個上下文持有的對象可以有業(yè)務(wù)對象,數(shù)據(jù)存取對象,資源,事物管理器等各種中間層對象。在這個上下文的基礎(chǔ)上,和web MVC相關(guān)還

2、會有一個上下文來保存控制器之類的MVC 對象,這樣就構(gòu)成了一個層次化的上下文結(jié)構(gòu)。在web 容器中啟動Spring 應(yīng)用程序就是一個建立這個上下文體系的過程。Spring 為web 應(yīng)用提供了上下文的擴(kuò)展接口WebApplicationContext:-Java 代碼public interface WebApplicationContext extends ApplicationContext /這里定義的常量用于在ServletContext 中存取根上下文String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE= /對WebApplicationCont

3、ext 來說,需要得到Web 容器的ServletContextServletContext getServletContext(;public interface WebApplicationContext extends ApplicationContext /這里定義的常量用于在ServletContext 中存取根上下文./對WebApplicationContext 來說,需要得到Web 容器的ServletContextServletContext getServletContext(;而一般的啟動過程,Spring 會使用一個默認(rèn)的實現(xiàn),XmlWebApplicationCont

4、ext 這個上下文實現(xiàn)作為在web 容器中的根上下文容器被建立起來,具體的建立過程在下面我們會詳細(xì)分析。Java 代碼public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext /* 這是和web 部署相關(guān)的位置信息,用來作為默認(rèn)的根上下文bean 定義信息的存放位置*/public static final String DEFAULT_CONFIG_LOCATION = /WEB-INF/applicationContext.xml; public static final S

5、tring DEFAULT_CONFIG_LOCATION_PREFIX = /WEB-INF/;public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = .xml;/我們又看到了熟悉的loadBeanDefinition, 就像我們前面對IOC 容器的分析中一樣,這個加載工程在容器的refresh(的時候啟動。protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory throws IOException /對于XmlWebApplicatio

6、nContext, 當(dāng)然使用的是XmlBeanDefinitionReader 來對bean 定義信息來進(jìn)行解析XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory;beanDefinitionReader.setResourceLoader(this;beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this;initBeanDefinitionReader(beanDefinitionRea

7、der;loadBeanDefinitions(beanDefinitionReader;protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader /使用XmlBeanDefinitionReader 來讀入bean 定義信息protected void loadBeanDefinitions(XmlBeanDefinitionReaderreader throwsBeansException, IOException String configLocations = getConf

8、igLocations(;if (configLocations != null for (int i = 0; i configLocations.length; i+ reader.loadBeanDefinitions(configLocationsi; /這里取得bean 定義信息位置,默認(rèn)的地方是/WEB-INF/applicationContext.xml protected String getDefaultConfigLocations( if (getNamespace( != null return new String DEFAULT_CONFIG_LOCATION_PR

9、EFIX + getNamespace( + DEFAULT_CONFIG_LOCATION_SUFFIX;else return new String DEFAULT_CONFIG_LOCATION;public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext /* 這是和web 部署相關(guān)的位置信息,用來作為默認(rèn)的根上下文bean 定義信息的存放位置*/public static final String DEFAULT_CONFIG_LOCATION = /WEB-INF/app

10、licationContext.xml; public static final String DEFAULT_CONFIG_LOCATION_PREFIX = /WEB-INF/;public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = .xml;/我們又看到了熟悉的loadBeanDefinition, 就像我們前面對IOC 容器的分析中一樣,這個加載工程在容器的refresh(的時候啟動。protected void loadBeanDefinitions(DefaultListableBeanFactory beanFact

11、ory throws IOException /對于XmlWebApplicationContext, 當(dāng)然使用的是XmlBeanDefinitionReader 來對bean 定義信息來進(jìn)行解析XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory;beanDefinitionReader.setResourceLoader(this;beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this;

12、initBeanDefinitionReader(beanDefinitionReader;loadBeanDefinitions(beanDefinitionReader;protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader /使用XmlBeanDefinitionReader 來讀入bean 定義信息protected void loadBeanDefinitions(XmlBeanDefinitionReader reader throws BeansException,

13、IOException String configLocations = getConfigLocations(;if (configLocations != null for (int i = 0; i configLocations.length; i+ reader.loadBeanDefinitions(configLocationsi;/這里取得bean 定義信息位置,默認(rèn)的地方是/WEB-INF/applicationContext.xmlprotected String getDefaultConfigLocations( if (getNamespace( != null re

14、turn new String DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace( + DEFAULT_CONFIG_LOCATION_SUFFIX;else return new String DEFAULT_CONFIG_LOCATION;對于一個Spring 激活的web 應(yīng)用程序,可以通過使用Spring 代碼聲明式的指定在web 應(yīng)用程序啟動時載入應(yīng)用程序上下文(WebApplicationContext,Spring 的ContextLoader 是提供這樣性能的類,我們可以使用 ContextLoaderServlet 或者Context

15、LoaderListener 的啟動時載入的Servlet 來實例化Spring IOC 容器為什么會有兩個不同的類來裝載它呢,這是因為它們的使用需要區(qū)別不同的Servlet 容器支持的Serlvet 版本。但不管是 ContextLoaderSevlet 還是 ContextLoaderListener 都使用ContextLoader 來完成實際的WebApplicationContext 的初始化工作。這個ContextLoder 就像是Spring Web應(yīng)用程序在Web 容器中的加載器booter 。當(dāng)然這些Servlet 的具體使用我們都要借助web 容器中的部署描述符來進(jìn)行相關(guān)的

16、定義。下面我們使用ContextLoaderListener 作為載入器作一個詳細(xì)的分析,這個Servlet 的監(jiān)聽器是根上下文被載入的地方,也是整個 Spring web 應(yīng)用加載上下文的第一個地方;從加載過程我們可以看到,首先從Servlet 事件中得到ServletContext ,然后可以讀到配置好的在web.xml 的中的各個屬性值,然后ContextLoder 實例化WebApplicationContext 并完成其載入和初始化作為根上下文。當(dāng)這個根上下文被載入后,它被綁定到web 應(yīng)用程序的ServletContext 上。任何需要訪問該ApplicationContext 的

17、應(yīng)用程序代碼都可以從WebApplicationContextUtils 類的靜態(tài)方法來得到:Java 代碼WebApplicationContext getWebApplicationContext(ServletContext scWebApplicationContext getWebApplicationContext(ServletContext sc以Tomcat 作為Servlet 容器為例,下面是具體的步驟:1.Tomcat 啟動時需要從web.xml 中讀取啟動參數(shù),在web.xml 中我們需要對ContextLoaderListener 進(jìn)行配置,對于在web 應(yīng)用啟動入口

18、是在ContextLoaderListener 中的初始化部分;從Spring MVC 上看,實際上在web 容器中維護(hù)了一系列的IOC 容器,其中在ContextLoader 中載入的IOC 容器作為根上下文而存在于 ServletContext 中。Java 代碼/這里對根上下文進(jìn)行初始化。public void contextInitialized(ServletContextEvent event /這里創(chuàng)建需要的ContextLoaderthis.contextLoader = createContextLoader(;/這里使用ContextLoader 對根上下文進(jìn)行載入和初始化

19、/這里對根上下文進(jìn)行初始化。public void contextInitialized(ServletContextEvent event /這里創(chuàng)建需要的ContextLoaderthis.contextLoader = createContextLoader(;/這里使用ContextLoader 對根上下文進(jìn)行載入和初始化通過ContextLoader 建立起根上下文的過程, 我們可以在ContextLoader 中看到:Java 代碼public WebApplicationContext initWebApplicationContext(ServletContext servle

20、tContext throws IllegalStateException, BeansException /這里先看看是不是已經(jīng)在ServletContext 中存在上下文, 如果有說明前面已經(jīng)被載入過,或者是配置文件有錯誤。if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE != null /直接拋出異常try / 這里載入根上下文的父上下文ApplicationContext parent = loadParentContext(servletContext

21、;/這里創(chuàng)建根上下文作為整個應(yīng)用的上下文同時把它存到ServletContext 中去, 注意這里使用的ServletContext 的屬性值是/ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,以后的應(yīng)用都是根據(jù)這個屬性值來取得根上下文的 - 往往作為自己上下文的父上下文this.context = createWebApplicationContext(servletContext, parent;servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTR

22、IBUTE, this.context;.return this.context;public WebApplicationContext initWebApplicationContext(ServletContext servletContext throws IllegalStateException, BeansException /這里先看看是不是已經(jīng)在ServletContext 中存在上下文, 如果有說明前面已經(jīng)被載入過,或者是配置文件有錯誤。if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICA

23、TION_CONTEXT_ATTRIBUTE != null /直接拋出異常.try / 這里載入根上下文的父上下文ApplicationContext parent = loadParentContext(servletContext;/這里創(chuàng)建根上下文作為整個應(yīng)用的上下文同時把它存到ServletContext 中去, 注意這里使用的ServletContext 的屬性值是/ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,以后的應(yīng)用都是根據(jù)這個屬性值來取得根上下文的 - 往往作為自己上下文的父上下文this.context = createWebApplica

24、tionContext(servletContext, parent;servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context;.return this.context;.建立根上下文的父上下文使用的是下面的代碼,取決于在web.xml 中定義的參數(shù):locatorFactorySelector ,這是一個可選參數(shù):Java 代碼protected ApplicationContext loadParentContext(ServletContex

25、t servletContextthrows BeansException ApplicationContext parentContext = null;String locatorFactorySelector= servletContext.getInitParameter(LOCATOR_FACTORY_SELECTOR_PARAM;String parentContextKey= servletContext.getInitParameter(LOCATOR_FACTORY_KEY_PARAM;if (locatorFactorySelector != null BeanFactor

26、yLocator locator=ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector;./得到根上下文的父上下文的引用this.parentContextRef = locator.useBeanFactory(parentContextKey;/這里建立得到根上下文的父上下文return parentContext;protected ApplicationContext loadParentContext(ServletContext servletContextthrows BeansExceptio

27、n ApplicationContext parentContext = null;String locatorFactorySelector= servletContext.getInitParameter(LOCATOR_FACTORY_SELECTOR_PARAM;String parentContextKey= servletContext.getInitParameter(LOCATOR_FACTORY_KEY_PARAM;if (locatorFactorySelector != null BeanFactoryLocator locator=ContextSingletonBea

28、nFactoryLocator.getInstance(locatorFactorySelector;./得到根上下文的父上下文的引用this.parentContextRef = locator.useBeanFactory(parentContextKey;/這里建立得到根上下文的父上下文return parentContext;得到根上下文的父上下文以后,就是根上下文的創(chuàng)建過程:Java 代碼protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, Applicat

29、ionContext parent throws BeansException /這里需要確定我們載入的根WebApplication 的類型,由在web.xml 中配置的contextClass 中配置的參數(shù)可以決定我們需要載入什么樣的ApplicationContext,/如果沒有使用默認(rèn)的。Class contextClass = determineContextClass(servletContext;/這里就是上下文的創(chuàng)建過程ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext BeanUt

30、ils.instantiateClass(contextClass; /這里保持對父上下文和ServletContext 的引用到根上下文中wac.setParent(parent;wac.setServletContext(servletContext;/這里從web.xml 中取得相關(guān)的初始化參數(shù)String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM; if (configLocation != null wac.setConfigLocations(StringUtils.tokenize

31、ToStringArray(configLocation,ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS; /這里對WebApplicationContext 進(jìn)行初始化,我們又看到了熟悉的refresh 調(diào)用。 wac.refresh(;return wac;protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, ApplicationContext parent throws BeansExc

32、eption /這里需要確定我們載入的根WebApplication 的類型,由在web.xml 中配置的contextClass 中配置的參數(shù)可以決定我們需要載入什么樣的ApplicationContext,/如果沒有使用默認(rèn)的。Class contextClass = determineContextClass(servletContext;./這里就是上下文的創(chuàng)建過程ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContextBeanUtils.instantiateClass(contextClass

33、;/這里保持對父上下文和ServletContext 的引用到根上下文中wac.setParent(parent;wac.setServletContext(servletContext;/這里從web.xml 中取得相關(guān)的初始化參數(shù)String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM; if (configLocation != null wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,Confi

34、gurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS; /這里對WebApplicationContext 進(jìn)行初始化,我們又看到了熟悉的refresh 調(diào)用。 wac.refresh(;return wac;初始化根ApplicationContext 后將其存儲到SevletContext 中去以后, 這樣就建立了一個全局的關(guān)于整個應(yīng)用的上下文。這個根上下文會被以后的DispatcherServlet 初始化自己的時候作為自己ApplicationContext 的父上下文。這個在對 DispatcherServlet 做分析的時候

35、我們可以看看到。3. 完成對ContextLoaderListener 的初始化以后, Tomcat 開始初始化DispatchServlet ,- 還記得我們在web.xml 中隊載入次序進(jìn)行了定義。DispatcherServlet 會建立自己的ApplicationContext, 同時建立這個自己的上下文的時候會從ServletContext 中得到根上下文作為父上下文, 然后再對自己的上下文進(jìn)行初始化,并最后存到 ServletContext 中去供以后檢索和使用??梢詮腄ispatchServlet 的父類FrameworkServlet 的代碼中看到大致的初始化過程,整個Appl

36、icationContext 的創(chuàng)建過程和ContextLoder 創(chuàng)建的過程相類似:Java 代碼protected final void initServletBean( throws ServletException, BeansException try /這里是對上下文的初始化過程。this.webApplicationContext = initWebApplicationContext(;/在完成對上下文的初始化過程結(jié)束后,根據(jù)bean 配置信息建立MVC 框架的各個主要元素initFrameworkServlet(;.protected final void initServl

37、etBean( throws ServletException, BeansException .try /這里是對上下文的初始化過程。this.webApplicationContext = initWebApplicationContext(;/在完成對上下文的初始化過程結(jié)束后,根據(jù)bean 配置信息建立MVC 框架的各個主要元素initFrameworkServlet(;.對initWebApplicationContext(調(diào)用的代碼如下:Java 代碼protected WebApplicationContext initWebApplicationContext( throws B

38、eansException /這里調(diào)用WebApplicationContextUtils 靜態(tài)類來得到根上下文WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext(;/創(chuàng)建當(dāng)前DispatcherServlet 的上下文,其上下文種類使用默認(rèn)的在FrameworkServlet 定義好的:DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;WebApplicationContext wac

39、 = createWebApplicationContext(parent;.if (isPublishContext( /把當(dāng)前建立的上下文存到ServletContext 中去,注意使用的屬性名是和當(dāng)前Servlet 名相關(guān)的。String attrName = getServletContextAttributeName(;getServletContext(.setAttribute(attrName, wac;return wac;protected WebApplicationContext initWebApplicationContext( throws BeansExcept

40、ion /這里調(diào)用WebApplicationContextUtils 靜態(tài)類來得到根上下文WebApplicationContext parent=WebApplicationContextUtils.getWebApplicationContext(getServletContext(;/創(chuàng)建當(dāng)前DispatcherServlet 的上下文,其上下文種類使用默認(rèn)的在FrameworkServlet 定義好的:DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class; WebApplicationContext wac = createWe

41、bApplicationContext(parent;.if (isPublishContext( /把當(dāng)前建立的上下文存到ServletContext 中去,注意使用的屬性名是和當(dāng)前Servlet 名相關(guān)的。String attrName = getServletContextAttributeName(;getServletContext(.setAttribute(attrName, wac;return wac;其中我們看到調(diào)用了WebApplicationContextUtils 的靜態(tài)方法得到根ApplicationContext:Java 代碼public static WebA

42、pplicationContext getWebApplicationContext(ServletContext sc /很簡單,直接從ServletContext 中通過屬性名得到根上下文Object attr = sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE; .return (WebApplicationContext attr;然后創(chuàng)建DispatcherServlet 自己的WebApplicationContext:protected WebApplicationConte

43、xt createWebApplicationContext(WebApplicationContext parentthrows BeansException ./這里使用了BeanUtils 直接得到WebApplicationContext,ContextClass 是前面定義好的DEFAULT_CONTEXT_CLASS =/XmlWebApplicationContext.class;ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContextBeanUtils.instantiateClass(g

44、etContextClass(;/這里配置父上下文,就是在ContextLoader 中建立的根上下文wac.setParent(parent;/保留ServletContext 的引用和相關(guān)的配置信息。wac.setServletContext(getServletContext(;wac.setServletConfig(getServletConfig(;wac.setNamespace(getNamespace(;/這里得到ApplicationContext 配置文件的位置if (getContextConfigLocation( != null wac.setConfigLocat

45、ions(StringUtils.tokenizeToStringArray(getContextConfigLocation(,ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS;/這里調(diào)用ApplicationContext 的初始化過程,同樣需要使用refresh( wac.refresh(;return wac;public static WebApplicationContext getWebApplicationContext(ServletContext sc /很簡單,直接從ServletContext 中通

46、過屬性名得到根上下文Object attr = sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE; .return (WebApplicationContext attr;然后創(chuàng)建DispatcherServlet 自己的WebApplicationContext:protected WebApplicationContext createWebApplicationContext(WebApplicationContext parentthrows BeansException ./這里使

47、用了BeanUtils 直接得到WebApplicationContext,ContextClass 是前面定義好的DEFAULT_CONTEXT_CLASS =/XmlWebApplicationContext.class;ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContextBeanUtils.instantiateClass(getContextClass(;/這里配置父上下文,就是在ContextLoader 中建立的根上下文wac.setParent(parent;/保留ServletCont

48、ext 的引用和相關(guān)的配置信息。wac.setServletContext(getServletContext(;wac.setServletConfig(getServletConfig(;wac.setNamespace(getNamespace(;/這里得到ApplicationContext 配置文件的位置if (getContextConfigLocation( != null wac.setConfigLocations(StringUtils.tokenizeToStringArray(getContextConfigLocation(,ConfigurableWebApplic

49、ationContext.CONFIG_LOCATION_DELIMITERS;/這里調(diào)用ApplicationContext 的初始化過程,同樣需要使用refresh(wac.refresh(;return wac;4. 然后就是DispatchServlet 中對Spring MVC 的配置過程,首先對配置文件中的定義元素進(jìn)行配置請注意這個時候我們的WebApplicationContext 已經(jīng)建立起來了,也意味著DispatcherServlet 有自己的定義資源,可以需要從web.xml 中讀取bean 的配置信息,通常我們會使用單獨(dú)的xml 文件來配置MVC 中各個要素定義,這里和

50、web 容器相關(guān)的加載過程實際上已經(jīng)完成了,下面的處理和普通的Spring 應(yīng)用程序的編寫沒有什么太大的差別,我們先看看MVC 的初始化過程:Java 代碼protected void initFrameworkServlet( throws ServletException, BeansException initMultipartResolver(;initLocaleResolver(;initThemeResolver(;initHandlerMappings(;initHandlerAdapters(;initHandlerExceptionResolvers(;initReques

51、tToViewNameTranslator(;initViewResolvers(;protected void initFrameworkServlet( throws ServletException, BeansException initMultipartResolver(;initLocaleResolver(;initThemeResolver(;initHandlerMappings(;initHandlerAdapters(;initHandlerExceptionResolvers(;initRequestToViewNameTranslator(;initViewResol

52、vers(;5. 這樣MVC 的框架就建立起來了,DispatchServlet 對接受到的HTTP Request 進(jìn)行分發(fā)處理由doService(完成,具體的MVC 處理過程我們在doDispatch(中完成,其中包括使用Command 模式建立執(zhí)行鏈,顯示模型數(shù)據(jù)等,這些處理我們都可以在DispatcherServlet 的代碼中看到:Java 代碼protected void doService(HttpServletRequest request, HttpServletResponse response throws Exception try doDispatch(request, response;.protected void doService(HttpServletRequest request, HttpServletResponse response throws Exception .try doDispatch(request, response;.實際的請求分發(fā)由doDispatch(request,response來完成:Java 代碼protected void doDispatch(final Http

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論