精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

SpringMVC 初始化流程分析

開發(fā) 前端
框架源碼是我們 Coding 晉級中的必修課,SSM 應(yīng)該算是小伙伴們?nèi)粘=佑|最多的框架了,這其中 SpringMVC 初始化流程相對來說要簡單一些,因此今天松哥就先來和大家分析一下 SpringMVC 初始化流程。

[[387214]]

框架源碼是我們 Coding 晉級中的必修課,SSM 應(yīng)該算是小伙伴們?nèi)粘=佑|最多的框架了,這其中 SpringMVC 初始化流程相對來說要簡單一些,因此今天松哥就先來和大家分析一下 SpringMVC 初始化流程。

即使你沒看過 SpringMVC 的源碼,估計也聽說過:DispatcherServlet 是 SpringMVC 的大腦,它負(fù)責(zé)整個 SpringMVC 的調(diào)度工作,是 SpringMVC 中最最核心的類,SpringMVC 整個頂層架構(gòu)設(shè)計都體現(xiàn)在這里,所以搞明白 DispatcherServlet 的源碼,基本上 SpringMVC 的工作原理也就了然于胸了。

然而 DispatcherServlet 繼承自 FrameworkServlet,F(xiàn)rameworkServlet 又繼承自 HttpServletBean,如下圖:

 

因此我們的分析就從 HttpServletBean 開始。

1.HttpServletBean

HttpServletBean繼承自 HttpServlet,它負(fù)責(zé)將 init-param 中的參數(shù)注入到當(dāng)前 Servlet 實例的屬性中,同時也為子類提供了增加 requiredProperties 的能力,需要注意的是 HttpServletBean 并不依賴于 Spring 容器。

大家知道,HttpServlet 的初始化是從 init 方法開始的,所以我們就先從 HttpServletBean 的 init 方法開始看起:

  1. @Override 
  2. public final void init() throws ServletException { 
  3.  // Set bean properties from init parameters. 
  4.  PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); 
  5.  if (!pvs.isEmpty()) { 
  6.   try { 
  7.    BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); 
  8.    ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); 
  9.    bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); 
  10.    initBeanWrapper(bw); 
  11.    bw.setPropertyValues(pvs, true); 
  12.   } 
  13.   catch (BeansException ex) { 
  14.    if (logger.isErrorEnabled()) { 
  15.     logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); 
  16.    } 
  17.    throw ex; 
  18.   } 
  19.  } 
  20.  // Let subclasses do whatever initialization they like
  21.  initServletBean(); 

在這個方法里,首先獲取到 Servlet 的所有配置并轉(zhuǎn)為 PropertyValues,然后通過 BeanWrapper 修改目標(biāo) Servlet 的相關(guān)屬性。BeanWrapper 是 Spring 中提供一個工具,使用它可以修改一個對象的屬性,像下面這樣:

  1. public class Main { 
  2.     public static void main(String[] args) { 
  3.         User user = new User(); 
  4.         BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(user); 
  5.         beanWrapper.setPropertyValue("username""itboyhub"); 
  6.         PropertyValue pv = new PropertyValue("address""www.itboyhub.com"); 
  7.         beanWrapper.setPropertyValue(pv); 
  8.         System.out.println("user = " + user); 
  9.     } 

最終輸出:

  1. user = User{username='itboyhub', address='www.itboyhub.com'

所以前面的 bw 實際上就代表當(dāng)前 DispatcherServlet 對象。

通過 BeanWrapper 修改目標(biāo) Servlet 的相關(guān)屬性時,有一個 initBeanWrapper 方法是空方法,開發(fā)者如有需要可以在子類中實現(xiàn)該方法,并且完成一些初始化操作。

屬性配置完成后,最終調(diào)用 initServletBean 方法進(jìn)行 Servlet 初始化,然而該方法也是一個空方法,在子類中實現(xiàn)。

這就是 HttpServletBean 所做的事情,比較簡單,加載 Servlet 相關(guān)屬性并設(shè)置給當(dāng)前 Servlet 對象,然后調(diào)用 initServletBean 方法繼續(xù)完成 Servlet 的初始化操作。

2.FrameworkServlet

從前面的介紹可知,F(xiàn)rameworkServlet 初始化的入口方法就是 initServletBean,因此我們就從 FrameworkServlet#initServletBean 方法開始看起:

  1. @Override 
  2. protected final void initServletBean() throws ServletException { 
  3.  //省略... 
  4.  try { 
  5.   this.webApplicationContext = initWebApplicationContext(); 
  6.   initFrameworkServlet(); 
  7.  } 
  8.  catch (ServletException | RuntimeException ex) { 
  9.   //省略... 
  10.  } 

這個方法原本挺長的,但是拋開日志打印異常拋出,剩下的核心代碼其實就兩行:

initWebApplicationContext 方法用來初始化 WebApplicationContext。

initFrameworkServlet 方法用來初始化 FrameworkServlet,但是這個方法是一個空方法,沒有具體的實現(xiàn)。本來子類可以重寫該方法做一些初始化操作,但是實際上子類并沒有重寫該方法,所以這個方法我們就暫且忽略之,不去分析了。

那么這里最為重要的其實就是 initWebApplicationContext 方法了,我們一起來看下:

  1. protected WebApplicationContext initWebApplicationContext() { 
  2.  WebApplicationContext rootContext = 
  3.    WebApplicationContextUtils.getWebApplicationContext(getServletContext()); 
  4.  WebApplicationContext wac = null
  5.  if (this.webApplicationContext != null) { 
  6.   wac = this.webApplicationContext; 
  7.   if (wac instanceof ConfigurableWebApplicationContext) { 
  8.    ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; 
  9.    if (!cwac.isActive()) { 
  10.     if (cwac.getParent() == null) { 
  11.      cwac.setParent(rootContext); 
  12.     } 
  13.     configureAndRefreshWebApplicationContext(cwac); 
  14.    } 
  15.   } 
  16.  } 
  17.  if (wac == null) { 
  18.   wac = findWebApplicationContext(); 
  19.  } 
  20.  if (wac == null) { 
  21.   wac = createWebApplicationContext(rootContext); 
  22.  } 
  23.  if (!this.refreshEventReceived) { 
  24.   synchronized (this.onRefreshMonitor) { 
  25.    onRefresh(wac); 
  26.   } 
  27.  } 
  28.  if (this.publishContext) { 
  29.   String attrName = getServletContextAttributeName(); 
  30.   getServletContext().setAttribute(attrName, wac); 
  31.  } 
  32.  return wac; 

這里的邏輯也比較清晰:

1.首先獲取 rootContext。在默認(rèn)情況下,Spring 會將容器設(shè)置為 ServletContext 的一個屬性,屬性的 key 為 org.springframework.web.context.WebApplicationContext.ROOT,所以根據(jù)這個 key 就可以調(diào)用 ServletContext#getAttribute 方法獲取到 rootContext 了。

2.獲取 WebApplicationContext 實例,也就是給 wac 變量賦值的過程,這里存在三種可能性:1.如果已經(jīng)通過構(gòu)造方法給 webApplicationContext 賦值了,則直接將其賦給 wac 變量,同時,如果需要設(shè)置 parent 就設(shè)置,需要刷新就刷新。這種方式適用于 Servlet3.0 以后的環(huán)境,因為從 Servlet3.0 開始,才支持直接調(diào)用 ServletContext.addServlet 方法去注冊 Servlet,手動注冊的時候就可以使用自己提前準(zhǔn)備好的 WebApplicationContext 了,這塊松哥在我錄制的 Spring Boot 視頻中也講過,感興趣的小伙伴可以在公眾號后臺回復(fù) vhr 查看視頻詳情;2.如果第一步?jīng)]能成功給 wac 賦值,那么調(diào)用 findWebApplicationContext 方法嘗試去 ServletContext 中查找 WebApplicationContext 對象,找到了就賦值給 wac;3.如果第二步?jīng)]能成功給 wac 賦值,那么調(diào)用 createWebApplicationContext 方法創(chuàng)建一個 WebApplicationContext 對象并賦值給 wac,一般來說都是通過這種方式創(chuàng)建的 WebApplicationContext。這三套組合拳下來,wac 肯定是有值了。

3.當(dāng) ContextRefreshedEvent 事件沒有觸發(fā)時,調(diào)用 onRefresh 方法完成容器刷新(由于第一種和第三種獲取 WebApplicationContext 的方式最終都會調(diào)用 configureAndRefreshWebApplicationContext 方法,然后發(fā)布事件,再將 refreshEventReceived 變量標(biāo)記為 true,所以實際上只有第二種方式獲取 wac 實例的時候,這里才會刷新,具體可以看下文分析)。

4.最后將 wac 保存到到 ServletContext 中。保存的時候會根據(jù) publishContext 變量的值來決定是否保存,publishContext 可以在 web.xml 中配置 Servlet 時通過 init-param 進(jìn)行配置,保存的目的是為了方便獲取。

上面的這些步驟中,通過 createWebApplicationContext 方法創(chuàng)建 WebApplicationContext 對象需要和大家細(xì)說下,因為一般情況下就是通過這種方式創(chuàng)建的 WebApplicationContext。我們來看一下相關(guān)的方法:

  1. protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) { 
  2.  Class<?> contextClass = getContextClass(); 
  3.  if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { 
  4.   throw new ApplicationContextException( 
  5.     "Fatal initialization error in servlet with name '" + getServletName() + 
  6.     "': custom WebApplicationContext class [" + contextClass.getName() + 
  7.     "] is not of type ConfigurableWebApplicationContext"); 
  8.  } 
  9.  ConfigurableWebApplicationContext wac = 
  10.    (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); 
  11.  wac.setEnvironment(getEnvironment()); 
  12.  wac.setParent(parent); 
  13.  String configLocation = getContextConfigLocation(); 
  14.  if (configLocation != null) { 
  15.   wac.setConfigLocation(configLocation); 
  16.  } 
  17.  configureAndRefreshWebApplicationContext(wac); 
  18.  return wac; 
  19. protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) { 
  20.  if (ObjectUtils.identityToString(wac).equals(wac.getId())) { 
  21.   // The application context id is still set to its original default value 
  22.   // -> assign a more useful id based on available information 
  23.   if (this.contextId != null) { 
  24.    wac.setId(this.contextId); 
  25.   } 
  26.   else { 
  27.    // Generate default id... 
  28.    wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + 
  29.      ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName()); 
  30.   } 
  31.  } 
  32.  wac.setServletContext(getServletContext()); 
  33.  wac.setServletConfig(getServletConfig()); 
  34.  wac.setNamespace(getNamespace()); 
  35.  wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener())); 
  36.  // The wac environment's #initPropertySources will be called in any case when the context 
  37.  // is refreshed; do it eagerly here to ensure servlet property sources are in place for 
  38.  // use in any post-processing or initialization that occurs below prior to #refresh 
  39.  ConfigurableEnvironment env = wac.getEnvironment(); 
  40.  if (env instanceof ConfigurableWebEnvironment) { 
  41.   ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig()); 
  42.  } 
  43.  postProcessWebApplicationContext(wac); 
  44.  applyInitializers(wac); 
  45.  wac.refresh(); 

這里一共涉及到兩個方法:

createWebApplicationContext

首先獲取到創(chuàng)建類型,并檢查創(chuàng)建類型,沒問題的話調(diào)用 instantiateClass 方法完成創(chuàng)建工作,然后給創(chuàng)建好的 wac 對象配置各種屬性,配置的 configLocation 就是我們在 web.xml 文件中配置的 SpringMVC 配置文件路徑,默認(rèn)的文件路徑是/WEB-INF/[servletName]-servlet.xml。

configureAndRefreshWebApplicationContext

configureAndRefreshWebApplicationContext 方法主要也是配置&刷新 WebApplicationContext,在這個方法里會調(diào)用 addApplicationListener 為 wac 添加一個監(jiān)聽器,監(jiān)聽的是 ContextRefreshedEvent 事件,當(dāng)收到該事件后,會調(diào)用 FrameworkServlet 的 onApplicationEvent 方法,并在該方法中調(diào)用 onRefresh 方法完成刷新,刷新之后,會將 refreshEventReceived 變量標(biāo)記為 true。

  1. public void onApplicationEvent(ContextRefreshedEvent event) { 
  2.  this.refreshEventReceived = true
  3.  synchronized (this.onRefreshMonitor) { 
  4.   onRefresh(event.getApplicationContext()); 
  5.  } 

這就是 FrameworkServlet#initServletBean 方法的大致工作邏輯。這里涉及到了 onRefresh 方法,但是這是一個空方法,在子類 DispatcherServlet 中實現(xiàn)了,所以接下來我們就來看 DispatcherServlet。

3.DispatcherServlet

這里我們就不廢話了,直接來看 onRefresh 方法,如下:

  1. @Override 
  2. protected void onRefresh(ApplicationContext context) { 
  3.  initStrategies(context); 
  4. protected void initStrategies(ApplicationContext context) { 
  5.  initMultipartResolver(context); 
  6.  initLocaleResolver(context); 
  7.  initThemeResolver(context); 
  8.  initHandlerMappings(context); 
  9.  initHandlerAdapters(context); 
  10.  initHandlerExceptionResolvers(context); 
  11.  initRequestToViewNameTranslator(context); 
  12.  initViewResolvers(context); 
  13.  initFlashMapManager(context); 

在 onRefresh 方法中調(diào)用了 initStrategies 進(jìn)行初始化操作。initStrategies 的內(nèi)容其實很簡單,就是九個組件的初始化。九個的初始化流程比較類似,這里我們以常見的視圖解析器的初始化方法 initViewResolvers 為例,來一起看看初始化流程:

  1. private void initViewResolvers(ApplicationContext context) { 
  2.  this.viewResolvers = null
  3.  if (this.detectAllViewResolvers) { 
  4.   // Find all ViewResolvers in the ApplicationContext, including ancestor contexts. 
  5.   Map<String, ViewResolver> matchingBeans = 
  6.     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, truefalse); 
  7.   if (!matchingBeans.isEmpty()) { 
  8.    this.viewResolvers = new ArrayList<>(matchingBeans.values()); 
  9.    // We keep ViewResolvers in sorted order
  10.    AnnotationAwareOrderComparator.sort(this.viewResolvers); 
  11.   } 
  12.  } 
  13.  else { 
  14.   try { 
  15.    ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class); 
  16.    this.viewResolvers = Collections.singletonList(vr); 
  17.   } 
  18.   catch (NoSuchBeanDefinitionException ex) { 
  19.    // Ignore, we'll add a default ViewResolver later. 
  20.   } 
  21.  } 
  22.  // Ensure we have at least one ViewResolver, by registering 
  23.  // a default ViewResolver if no other resolvers are found. 
  24.  if (this.viewResolvers == null) { 
  25.   this.viewResolvers = getDefaultStrategies(context, ViewResolver.class); 
  26.   if (logger.isTraceEnabled()) { 
  27.    logger.trace("No ViewResolvers declared for servlet '" + getServletName() + 
  28.      "': using default strategies from DispatcherServlet.properties"); 
  29.   } 
  30.  } 

一開始的 viewResolvers 變量是一個集合,解析出來的視圖解析器對象都將放入這個集合中。

首先判斷 detectAllViewResolvers 變量是否為 true,如果為 true,則直接去查找 Spring 容器中的所有視圖解析器,將查找結(jié)果賦值給 viewResolvers,然后進(jìn)行排序。默認(rèn)情況下 detectAllViewResolvers 變量的值為 true,如果有需要,可以在 web.xml 中進(jìn)行配置,像下面這樣:

  1. <servlet> 
  2.     <servlet-name>springmvc</servlet-name
  3.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
  4.     <init-param> 
  5.         <param-name>contextConfigLocation</param-name
  6.         <param-value>classpath:spring-servlet.xml</param-value> 
  7.     </init-param> 
  8.     <init-param> 
  9.         <param-name>detectAllViewResolvers</param-name
  10.         <param-value>false</param-value> 
  11.     </init-param> 
  12.     <load-on-startup>1</load-on-startup> 
  13. </servlet> 
  14. <servlet-mapping> 
  15.     <servlet-name>springmvc</servlet-name
  16.     <url-pattern>/</url-pattern> 
  17. </servlet-mapping> 

如果 detectAllViewResolvers 的值為 false,那么接下來就會去 Spring 容器中查找一個名為 viewResolver 的視圖解析器,此時查找到的就是一個單獨的視圖解析器。

一般來說,我們并不需要在 web.xml 中去配置 detectAllViewResolvers 的值,視圖解析器有多少個就加載多少個。

舉個簡單例子,我們在 SpringMVC 的配置文件中可能像下面這樣配置視圖解析器:

  1. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver"
  2.     <property name="prefix" value="/WEB-INF/jsp/"/> 
  3.     <property name="suffix" value=".jsp"/> 
  4. </bean> 

默認(rèn)情況下,這個 bean 的 id 有沒有都行,如果有,取什么值都可以,反正最終都是通過類型而不是 id 去查找的視圖解析器。但是如果你在 web.xml 中將 detectAllViewResolvers 修改為 false,那么這個 bean 的 id 取值就比較重要了,就一定要是 viewResolver。

如果在 Spring 容器中通過這兩種方式(通過類型查找或通過 id 查找)都沒有找到 ViewResolver 實例,那么會調(diào)用 getDefaultStrategies 方法去獲取一個默認(rèn)的 ViewResolver 實例。默認(rèn)實例的獲取方式如下:

 

  1. protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) { 
  2.  if (defaultStrategies == null) { 
  3.   try { 
  4.    // Load default strategy implementations from properties file. 
  5.    // This is currently strictly internal and not meant to be customized 
  6.    // by application developers. 
  7.    ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class); 
  8.    defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); 
  9.   } 
  10.   catch (IOException ex) { 
  11.    throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage()); 
  12.   } 
  13.  } 
  14.  String key = strategyInterface.getName(); 
  15.  String value = defaultStrategies.getProperty(key); 
  16.  if (value != null) { 
  17.   String[] classNames = StringUtils.commaDelimitedListToStringArray(value); 
  18.   List<T> strategies = new ArrayList<>(classNames.length); 
  19.   for (String className : classNames) { 
  20.    try { 
  21.     Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader()); 
  22.     Object strategy = createDefaultStrategy(context, clazz); 
  23.     strategies.add((T) strategy); 
  24.    } 
  25.    catch (ClassNotFoundException ex) { 
  26.     throw new BeanInitializationException( 
  27.       "Could not find DispatcherServlet's default strategy class [" + className + 
  28.       "] for interface [" + key + "]", ex); 
  29.    } 
  30.    catch (LinkageError err) { 
  31.     throw new BeanInitializationException( 
  32.       "Unresolvable class definition for DispatcherServlet's default strategy class [" + 
  33.       className + "] for interface [" + key + "]", err); 
  34.    } 
  35.   } 
  36.   return strategies; 
  37.  } 
  38.  else { 
  39.   return Collections.emptyList(); 
  40.  } 

這段代碼其實也比較簡單,就是通過反射去獲取默認(rèn)的視圖解析器。

首先給 defaultStrategies 賦值,defaultStrategies 的值實際上就是從 DispatcherServlet.properties 文件中加載到的,我們來看下這個文件內(nèi)容:

 

可以看到,這里一共定義了 8 個默認(rèn)的鍵值對,有的值是一個,有的值是多個。前面 initStrategies 方法中一共要初始化九個組件,這里默認(rèn)只定義了 8 個,少了一個 MultipartResolver,這也好理解,并非所有的項目都有文件上傳,而且即使有文件上傳,用哪一個具體的 MultipartResolver 也不好確定,還是要開發(fā)者自己決定。

defaultStrategies 其實加載到的就是這 8 個鍵值對,其中視圖解析器對應(yīng)的是 org.springframework.web.servlet.view.InternalResourceViewResolver,通過反射創(chuàng)建該類的實例,當(dāng) Spring 容器中不存在任何視圖解析器的時候,默認(rèn)的視圖解析器即此。

這就是 initViewResolvers 的工作流程,另外 8 個也和它差不多,唯一不同的是 initMultipartResolver,如下:

  1. private void initMultipartResolver(ApplicationContext context) { 
  2.  try { 
  3.   this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class); 
  4.  } 
  5.  catch (NoSuchBeanDefinitionException ex) { 
  6.   this.multipartResolver = null
  7.  } 

可以看到,它只是根據(jù) bean 的名字去查找 bean 實例,沒有去查找默認(rèn)的 MultipartResolver。

說到這里,松哥和大家多說一句 SpringMVC 配置中的小細(xì)節(jié),

  1. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver"
  2.     <property name="prefix" value="/WEB-INF/jsp/"/> 
  3.     <property name="suffix" value=".jsp"/> 
  4. </bean> 
  5. <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"
  6. </bean> 

上面這個關(guān)于視圖解析器和文件上傳解析器的配置,不知道小伙伴們有沒有注意過,視圖解析器的 id 可有可無,而文件上傳解析器的 id 必須是 multipartResolver,回顧我們上面的源碼分析,你就知道為啥了!

4.小結(jié)

好啦,這就是松哥和小伙伴們分享的 SpringMVC 的初始化流程,主要涉及到了 HttpServletBean、FrameworkServlet 以及 DispatcherServlet 三個實例,HttpServletBean 主要是加載 Servlet 配置的各種屬性并設(shè)置到 Servlet 上;FrameworkServlet 則主要是初始化了 WebApplicationContext;DispatcherServlet 則主要是初始化了自身的九個組件。

這只是初始化的流程,那么當(dāng)請求到來之后,請求的流程又是怎么樣的呢?這個松哥下篇文章來和大家分享~好啦,今天就先和小伙伴們聊這么多。

本文轉(zhuǎn)載自微信公眾號「江南一點雨」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系江南一點雨公眾號。

 

責(zé)任編輯:武曉燕 來源: 江南一點雨
相關(guān)推薦

2022-07-06 10:37:45

SpringServlet初始化

2023-05-03 23:48:24

Spring容器初始化

2009-09-17 16:06:22

C#數(shù)組初始化

2010-06-04 15:47:46

MySQL初始化roo

2023-11-12 23:08:17

C++初始化

2025-05-21 10:09:09

Spring 5.xIOC編程

2025-03-14 10:37:24

SpringSpring IOC容器

2022-05-10 10:06:03

Kafka

2009-09-08 09:48:34

LINQ初始化數(shù)組

2009-11-11 15:29:15

ADO初始化

2019-11-04 13:50:36

Java數(shù)組編程語言

2010-07-28 10:22:33

FlexApplica

2020-12-03 09:50:52

容器IoC流程

2011-06-17 15:29:44

C#對象初始化器集合初始化器

2024-01-15 06:34:09

Gin鏡像容器

2009-09-18 11:15:52

C#數(shù)組初始化

2009-09-25 16:55:08

Hibernate初始

2011-03-16 10:52:20

2009-12-16 14:04:04

Ruby對象初始化

2021-12-26 00:08:35

C++初始化列表
點贊
收藏

51CTO技術(shù)棧公眾號

成年人小视频在线观看| 亚洲自拍高清视频网站| 亚洲调教欧美在线| 亚洲www.| 国产精品国产三级国产aⅴ中文| 国产美女精品视频| 亚洲天堂黄色片| 精品久久久网| 一区二区日韩电影| 狠狠色噜噜狠狠色综合久| 精品人妻一区二区色欲产成人| 精品国产不卡| 日韩一区二区三区四区五区六区 | 国产一区二区网站| 国内综合精品午夜久久资源| 日韩电影在线观看中文字幕| 免费激情视频在线观看| 可以在线观看的av网站| 麻豆精品国产传媒mv男同| 欧美成人在线网站| 亚洲调教欧美在线| 亚洲成人1区| 亚洲mv在线观看| 蜜桃视频在线观看成人| 136福利视频导航| 最新日韩欧美| 色视频www在线播放国产成人| 日韩成人av影院| 精品肉辣文txt下载| 极品少妇一区二区| 欧美裸体男粗大视频在线观看| 亚欧美一区二区三区| 色戒汤唯在线观看| 综合久久久久久| 国产精品久久久久久久久久直播 | 亚洲九九九在线观看| 三级性生活视频| 亚洲天堂资源| 亚洲最大色网站| 亚洲国内在线| 免费在线超碰| 成人免费看的视频| 成人在线精品视频| 中文字幕 人妻熟女| 亚洲三级色网| 欧美另类精品xxxx孕妇| 99久久久无码国产精品不卡| 亚洲免费观看高清完整版在线观| 日韩免费高清av| 日日噜噜噜噜久久久精品毛片| 999精品网| 亚洲三级久久久| 日本高清不卡一区二区三| 天堂网在线资源| av不卡在线播放| 精品久久久久久乱码天堂| 熟妇人妻av无码一区二区三区| 本田岬高潮一区二区三区| 成人动漫视频在线观看完整版 | 日本一区二区欧美| 精品成人国产| 2019中文在线观看| 国产成人综合欧美精品久久| 久久国产成人| 国产精品第一区| 亚洲网站免费观看| 国产一区二区三区国产| 岛国一区二区三区高清视频| 可以免费看毛片的网站| av日韩在线网站| 蜜桃av色综合| 成人欧美一区| 1区2区3区精品视频| 日本黄网站色大片免费观看| 天堂av最新在线| 亚洲成人一区二区在线观看| 男人揉女人奶房视频60分| 国产精品迅雷| 欧美夫妻性生活| 激情综合激情五月| 九九久久成人| www.久久久久| 国产精品16p| 久久性色av| 成人亲热视频网站| 神宫寺奈绪一区二区三区| 久久久www成人免费无遮挡大片| 亚洲欧美丝袜| 成人影音在线| 精品视频一区二区不卡| 91人人澡人人爽| 夜夜春成人影院| xx视频.9999.com| 国产成人免费观看视频| 久久精品国产在热久久| 国产精品免费一区二区三区| 国产乱视频在线观看| 亚洲免费色视频| 日韩精品一区二区三区色欲av| 2019中文亚洲字幕| 亚洲欧美日韩视频一区| 黄页网站免费观看| 老司机亚洲精品| 91久久爱成人| www在线免费观看| 亚洲国产精品天堂| 激情图片中文字幕| 精品久久91| 午夜精品福利电影| 国产精品久久影视| 久久久久亚洲蜜桃| 欧日韩免费视频| 日韩福利在线观看| 国产丝袜高跟一区| 久久精品这里只有精品| 蜜桃av一区二区| 精品无人区一区二区三区| 国产鲁鲁视频在线观看特色| 色综合久久综合网欧美综合网| 在线播放国产视频| 91精品久久久久久久久久不卡| 2018日韩中文字幕| 亚洲老妇色熟女老太| ...中文天堂在线一区| 99视频精品免费| 秋霞影视一区二区三区| 欧美激情综合色综合啪啪五月| 国产精品无码天天爽视频| 欧美激情中文字幕| 黄www在线观看| 国产精品毛片视频| 欧美激情视频播放| 国产超碰人人模人人爽人人添| 国产精品久久久久三级| 天天爽天天爽夜夜爽| 亚洲激情77| 欧美一级大胆视频| 午夜视频在线免费播放| 亚洲成av人片观看| 免费看毛片的网站| 亚洲三级国产| 久久手机视频| 欧美一级鲁丝片| 亚洲精品xxx| 日本一级一片免费视频| 白白色 亚洲乱淫| 黄色成人在线看| 欧美成人一区在线观看| 97在线视频精品| 午夜视频免费在线| 欧美日韩在线视频首页| 三级黄色片网站| 亚洲女同同性videoxma| 免费国产一区| 欧美三区四区| 深夜福利一区二区| 888奇米影视| 亚洲免费视频中文字幕| wwwxxxx在线观看| 国产精品mm| 精品国产综合久久| 澳门av一区二区三区| 这里只有精品视频| 国产精选久久久| 亚洲影视在线播放| 欧美大片免费播放器| 男女精品网站| 亚洲aⅴ天堂av在线电影软件| 成人国产精选| 久久91亚洲精品中文字幕奶水 | 日韩精品999| 中文字幕一区二区人妻电影| 国产精品天天看| 午夜免费一级片| 在线观看的日韩av| 日本一区二区三区精品视频| 欧美xxxx网站| 欧美劲爆第一页| 免费福利在线视频| 538在线一区二区精品国产| 久久久久久国产精品免费播放| 99这里只有久久精品视频| 无码日韩人妻精品久久蜜桃| 99免费精品| 久久99久久精品国产| 日韩一区精品| 久久久噜噜噜久久| 国产免费av在线| 日韩一级免费观看| 中文字幕黄色片| 中文字幕一区二区三| 稀缺小u女呦精品呦| 日本视频一区二区| www.亚洲视频.com| 欧美自拍偷拍| 国产综合精品一区二区三区| 成人精品高清在线视频| 久久免费观看视频| 亚洲成人三级| 亚洲欧美日韩高清| 免费av网站观看| 欧美片网站yy| 人妻丰满熟妇av无码区| 玉足女爽爽91| 人人爽人人爽人人片| 成年人国产精品| 成人亚洲免费视频| 久久久久国产精品一区三寸| 日韩中文在线字幕| 久久av资源| 国产精品免费在线| 亚洲一区av| 国产精品久久91| 嗯啊主人调教在线播放视频 | 亚洲成人精品久久| 国产精品-色哟哟| 一本大道av伊人久久综合| 国产一级在线观看视频| 中文字幕一区二区不卡| 精品人妻一区二区三区四区| 99精品久久99久久久久| 人妻换人妻仑乱| 麻豆成人av在线| 91色国产在线| 久久一区亚洲| 播放灌醉水嫩大学生国内精品| 欧美日韩四区| 日韩亚洲欧美一区二区| 91精品一区二区三区综合| 亚洲欧美综合一区| 人人狠狠综合久久亚洲婷婷| 欧美激情论坛| 要久久爱电视剧全集完整观看| 国产日本一区二区三区| gogo人体一区| 成人自拍爱视频| 中文字幕一区日韩精品| 亚洲影院污污.| 麻豆国产一区二区三区四区| 成人h视频在线观看播放| 素人啪啪色综合| 国产精品欧美日韩一区二区| 欧美日韩亚洲国产| 国产精品久久久久久久久久久不卡 | 久久久久久久影视| 亚洲日本成人女熟在线观看| 你懂的视频在线| 国产亚洲人成a一在线v站| 韩国三级在线观看久| 一区二区欧美久久| lutube成人福利在线观看| 最近2019年中文视频免费在线观看| wwwxxx在线观看| 色伦专区97中文字幕| av网站在线免费| 国内精品免费午夜毛片| 一区二区精品伦理...| 国产成人精品网站| 黑人一区二区三区| 91视频国产高清| aaa国产精品视频| 国产另类第一区| 国产精品三级| 香蕉精品视频在线| 精品成人久久| 丁香婷婷激情网| 国内精品久久久久影院色 | 国产精品久久久久久久久毛片| 欧美性猛交xxxxxxxx| 国产巨乳在线观看| 亚洲精品国产综合区久久久久久久 | 巨胸喷奶水www久久久免费动漫| 91精品久久久久久久久久久久久| 精品视频成人| 久久av一区二区三区亚洲| 国产一区国产二区国产三区| 99热一区二区三区| 亚洲精品乱码| 天天色综合社区| 国产成人一区在线| 成年人网站免费看| 国产精品国产自产拍在线| 欧美黄色免费观看| 欧美性感美女h网站在线观看免费| 色婷婷久久综合中文久久蜜桃av| 欧美一区二区三区免费视频| 人妻妺妺窝人体色www聚色窝 | 日韩一级免费观看| 久久米奇亚洲| 欧美激情一区二区三区在线视频观看| 亚洲美女久久精品| 91久久中文字幕| 妖精视频一区二区三区| 男人日女人的bb| 日韩精品一级二级| 韩国av中国字幕| 国产精品国产成人国产三级| 奇米影视第四色777| 欧美精选午夜久久久乱码6080| 天堂8在线视频| 欧美日韩国产成人在线| 国产精品66| 久久国产欧美精品| 你懂的网址国产 欧美| 9久久婷婷国产综合精品性色 | 国产美女视频免费| 久久狠狠婷婷| 日本五十肥熟交尾| 亚洲欧美日韩中文播放 | 亚洲福利影院| 91免费看网站| 99久久精品网| 无码日韩人妻精品久久蜜桃| av不卡在线播放| 免费人成在线观看| 欧美日本乱大交xxxxx| 你懂的免费在线观看| 4438全国成人免费| 欧美黄视频在线观看| 中文字幕在线亚洲三区| 视频一区视频二区在线观看| 少妇户外露出[11p]| 亚洲一区自拍偷拍| 国产三级第一页| www.99久久热国产日韩欧美.com| 成人黄色图片网站| 欧洲一区二区日韩在线视频观看免费| 国产日韩欧美在线播放不卡| 99久久久无码国产精品性波多| 亚洲精品免费在线| av资源免费看| 久久久精品亚洲| 日韩伦理一区二区| 一本久道久久综合狠狠爱亚洲精品| 丝袜美腿亚洲色图| www.狠狠爱| 日韩欧美极品在线观看| 欧美精品a∨在线观看不卡| 97久久久免费福利网址| 精品午夜电影| 人妻av中文系列| 不卡av电影在线播放| 亚洲精品1区2区3区| 日韩av影视在线| 中文在线8资源库| 欧美日韩一区二区三区在线观看免| 亚洲欧美大片| 伊人网伊人影院| 91福利视频在线| 亚洲s色大片| 91久久爱成人| 999在线观看精品免费不卡网站| 亚洲欧美高清在线| 欧美性猛交xxxx久久久| 岛国视频免费在线观看| 国产美女91呻吟求| 亚洲有吗中文字幕| 四虎永久免费观看| 欧美性xxxxxxx| av在线天堂| 亚洲一区二区三区视频| 亚洲视频日本| 国产精品九九九九九| 欧美日韩精品一区二区三区蜜桃| 男人天堂久久久| 成人蜜桃视频| 午夜影院日韩| 波多野结衣喷潮| 欧美刺激午夜性久久久久久久| 老牛影视精品| 亚洲二区自拍| 国产sm精品调教视频网站| 好看的av在线| 日韩中文字幕免费| theporn国产在线精品| 欧美成人免费高清视频| 中文字幕一区在线观看| 韩国av免费在线观看| 国产精品99久久久久久白浆小说| 国产精品97| 中文乱码人妻一区二区三区视频| 欧美色视频一区| 大香伊人久久| 亚洲人成影视在线观看| 岛国av在线一区| 中文字幕免费视频观看| 欧美国产在线电影| 国产成人久久| 日本女人性视频| 在线观看欧美黄色| 手机av免费在线| 午夜一区二区三视频在线观看| 国产成人免费在线视频| 亚洲男人天堂网址| 久久99亚洲热视| 日韩激情一区| 久久精品女同亚洲女同13| 91精品国产欧美日韩| 欧美电影免费观看| 日韩a级在线观看|