广告
返回顶部
首页 > 资讯 > 前端开发 > html >SpringMVC初始化流程是什么
  • 313
分享到

SpringMVC初始化流程是什么

2024-04-02 19:04:59 313人浏览 泡泡鱼
摘要

本篇内容主要讲解“springMVC初始化流程是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springmvc初始化流程是什么”吧!框架源码是我们 cod

本篇内容主要讲解“springMVC初始化流程是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习springmvc初始化流程是什么”吧!

框架源码是我们 coding 晋级中的必修课,SSM 应该算是小伙伴们日常接触最多的框架了,这其中 SpringMVC  初始化流程相对来说要简单一些,因此今天松哥就先来和大家分析一下 SpringMVC 初始化流程。

即使你没看过 SpringMVC 的源码,估计也听说过:DispatcherServlet 是 SpringMVC 的大脑,它负责整个 SpringMVC  的调度工作,是 SpringMVC 中最最核心的类,SpringMVC 整个顶层架构设计都体现在这里,所以搞明白 DispatcherServlet  的源码,基本上 SpringMVC 的工作原理也就了然于胸了。

然而 DispatcherServlet 继承自 FrameworkServlet,FrameworkServlet 又继承自  httpservletBean,如下图:

SpringMVC初始化流程是什么

因此我们的分析就从 HttpServletBean 开始。

1.HttpServletBean

HttpServletBean继承自 HttpServlet,它负责将 init-param 中的参数注入到当前  Servlet 实例的属性中,同时也为子类提供了增加 requiredProperties 的能力,需要注意的是 HttpServletBean 并不依赖于  Spring 容器

大家知道,HttpServlet 的初始化是从 init 方法开始的,所以我们就先从 HttpServletBean 的 init 方法开始看起:

@Override public final void init() throws ServletException {  // Set bean properties from init parameters.  PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);  if (!pvs.isEmpty()) {   try {    BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);    ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());    bw.reGISterCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));    initBeanWrapper(bw);    bw.setPropertyValues(pvs, true);   }   catch (BeansException ex) {    if (logger.isErrorEnabled()) {     logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);    }    throw ex;   }  }  // Let subclasses do whatever initialization they like.  initServletBean(); }

在这个方法里,首先获取到 Servlet 的所有配置并转为 PropertyValues,然后通过 BeanWrapper 修改目标 Servlet  的相关属性。BeanWrapper 是 Spring 中提供一个工具,使用它可以修改一个对象的属性,像下面这样:

public class Main {     public static void main(String[] args) {         User user = new User();         BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(user);         beanWrapper.setPropertyValue("username", "itboyhub");         PropertyValue pv = new PropertyValue("address", "www.itboyhub.com");         beanWrapper.setPropertyValue(pv);         System.out.println("user = " + user);     } }

最终输出:

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

所以前面的 bw 实际上就代表当前 DispatcherServlet 对象。

通过 BeanWrapper 修改目标 Servlet 的相关属性时,有一个 initBeanWrapper  方法是空方法,开发者如有需要可以在子类中实现该方法,并且完成一些初始化操作。

属性配置完成后,最终调用 initServletBean 方法进行 Servlet 初始化,然而该方法也是一个空方法,在子类中实现。

这就是 HttpServletBean 所做的事情,比较简单,加载 Servlet 相关属性并设置给当前 Servlet 对象,然后调用  initServletBean 方法继续完成 Servlet 的初始化操作。

2.FrameworkServlet

从前面的介绍可知,FrameworkServlet 初始化的入口方法就是 initServletBean,因此我们就从  FrameworkServlet#initServletBean 方法开始看起:

@Override protected final void initServletBean() throws ServletException {  //省略...  try {   this.WEBApplicationContext = initWebApplicationContext();   initFrameworkServlet();  }  catch (ServletException | RuntimeException ex) {   //省略...  } }

这个方法原本挺长的,但是抛开日志打印异常抛出,剩下的核心代码其实就两行:

initWebApplicationContext 方法用来初始化 WebApplicationContext。

initFrameworkServlet 方法用来初始化  FrameworkServlet,但是这个方法是一个空方法,没有具体的实现。本来子类可以重写该方法做一些初始化操作,但是实际上子类并没有重写该方法,所以这个方法我们就暂且忽略之,不去分析了。

那么这里最为重要的其实就是 initWebApplicationContext 方法了,我们一起来看下:

protected WebApplicationContext initWebApplicationContext() {  WebApplicationContext rootContext =    WebApplicationContextUtils.getWebApplicationContext(getServletContext());  WebApplicationContext wac = null;  if (this.webApplicationContext != null) {   wac = this.webApplicationContext;   if (wac instanceof ConfigurableWebApplicationContext) {    ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;    if (!cwac.isActive()) {     if (cwac.getParent() == null) {      cwac.setParent(rootContext);     }     configureAndRefreshWebApplicationContext(cwac);    }   }  }  if (wac == null) {   wac = findWebApplicationContext();  }  if (wac == null) {   wac = createWebApplicationContext(rootContext);  }  if (!this.refreshEventReceived) {   synchronized (this.onRefreshMonitor) {    onRefresh(wac);   }  }  if (this.publishContext) {   String attrName = getServletContextAttributeName();   getServletContext().setAttribute(attrName, wac);  }  return wac; }

这里的逻辑也比较清晰:

1.首先获取 rootContext。在默认情况下,Spring 会将容器设置为 ServletContext 的一个属性,属性的 key 为  org.springframework.web.context.WebApplicationContext.ROOT,所以根据这个 key 就可以调用  ServletContext#getAttribute 方法获取到 rootContext 了。

2.获取 WebApplicationContext 实例,也就是给 wac 变量赋值的过程,这里存在三种可能性:1.如果已经通过构造方法给  webApplicationContext 赋值了,则直接将其赋给 wac 变量,同时,如果需要设置 parent 就设置,需要刷新就刷新。这种方式适用于  Servlet3.0 以后的环境,因为从 Servlet3.0 开始,才支持直接调用 ServletContext.addServlet 方法去注册  Servlet,手动注册的时候就可以使用自己提前准备好的 WebApplicationContext 了,这块松哥在我录制的 Spring Boot  视频中也讲过,感兴趣的小伙伴可以在公众号后台回复 vhr 查看视频详情;2.如果第一步没能成功给 wac 赋值,那么调用  findWebApplicationContext 方法尝试去 ServletContext 中查找 WebApplicationContext  对象,找到了就赋值给 wac;3.如果第二步没能成功给 wac 赋值,那么调用 createWebApplicationContext 方法创建一个  WebApplicationContext 对象并赋值给 wac,一般来说都是通过这种方式创建的  WebApplicationContext。这三套组合拳下来,wac 肯定是有值了。

3.当 ContextRefreshedEvent 事件没有触发时,调用 onRefresh 方法完成容器刷新(由于第一种和第三种获取  WebApplicationContext 的方式最终都会调用 configureAndRefreshWebApplicationContext  方法,然后发布事件,再将 refreshEventReceived 变量标记为 true,所以实际上只有第二种方式获取 wac  实例的时候,这里才会刷新,具体可以看下文分析)。

4.最后将 wac 保存到到 ServletContext 中。保存的时候会根据 publishContext  变量的值来决定是否保存,publishContext 可以在 web.xml 中配置 Servlet 时通过 init-param  进行配置,保存的目的是为了方便获取。

上面的这些步骤中,通过 createWebApplicationContext 方法创建 WebApplicationContext  对象需要和大家细说下,因为一般情况下就是通过这种方式创建的 WebApplicationContext。我们来看一下相关的方法:

protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {  Class<?> contextClass = getContextClass();  if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {   throw new ApplicationContextException(     "Fatal initialization error in servlet with name '" + getServletName() +     "': custom WebApplicationContext class [" + contextClass.getName() +     "] is not of type ConfigurableWebApplicationContext");  }  ConfigurableWebApplicationContext wac =    (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);  wac.setEnvironment(getEnvironment());  wac.setParent(parent);  String configLocation = getContextConfigLocation();  if (configLocation != null) {   wac.setConfigLocation(configLocation);  }  configureAndRefreshWebApplicationContext(wac);  return wac; } protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {  if (ObjectUtils.identityToString(wac).equals(wac.getId())) {   // The application context id is still set to its original default value   // -> assign a more useful id based on available infORMation   if (this.contextId != null) {    wac.setId(this.contextId);   }   else {    // Generate default id...    wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +      ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());   }  }  wac.setServletContext(getServletContext());  wac.setServletConfig(getServletConfig());  wac.setNamespace(getNamespace());  wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));  // The wac environment's #initPropertySources will be called in any case when the context  // is refreshed; do it eagerly here to ensure servlet property sources are in place for  // use in any post-processing or initialization that occurs below prior to #refresh  ConfigurableEnvironment env = wac.getEnvironment();  if (env instanceof ConfigurableWebEnvironment) {   ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());  }  postProcessWebApplicationContext(wac);  applyInitializers(wac);  wac.refresh(); }

这里一共涉及到两个方法:

createWebApplicationContext

首先获取到创建类型,并检查创建类型,没问题的话调用 instantiateClass 方法完成创建工作,然后给创建好的 wac 对象配置各种属性,配置的  configLocation 就是我们在 web.xml 文件中配置的 SpringMVC  配置文件路径,默认的文件路径是/WEB-INF/[servletName]-servlet.xml。

configureAndRefreshWebApplicationContext

configureAndRefreshWebApplicationContext 方法主要也是配置&刷新  WebApplicationContext,在这个方法里会调用 addApplicationListener 为 wac 添加一个监听器,监听的是  ContextRefreshedEvent 事件,当收到该事件后,会调用 FrameworkServlet 的 onApplicationEvent  方法,并在该方法中调用 onRefresh 方法完成刷新,刷新之后,会将 refreshEventReceived 变量标记为 true。

public void onApplicationEvent(ContextRefreshedEvent event) {  this.refreshEventReceived = true;  synchronized (this.onRefreshMonitor) {   onRefresh(event.getApplicationContext());  } }

这就是 FrameworkServlet#initServletBean 方法的大致工作逻辑。这里涉及到了 onRefresh  方法,但是这是一个空方法,在子类 DispatcherServlet 中实现了,所以接下来我们就来看 DispatcherServlet。

3.DispatcherServlet

这里我们就不废话了,直接来看 onRefresh 方法,如下:

@Override protected void onRefresh(ApplicationContext context) {  initStrategies(context); } protected void initStrategies(ApplicationContext context) {  initMultipartResolver(context);  initLocaleResolver(context);  initThemeResolver(context);  initHandlerMappings(context);  initHandlerAdapters(context);  initHandlerExceptionResolvers(context);  initRequestToViewNameTranslator(context);  initViewResolvers(context);  initFlashMapManager(context); }

在 onRefresh 方法中调用了 initStrategies 进行初始化操作。initStrategies  的内容其实很简单,就是九个组件的初始化。九个的初始化流程比较类似,这里我们以常见的视图解析器的初始化方法 initViewResolvers  为例,来一起看看初始化流程:

private void initViewResolvers(ApplicationContext context) {  this.viewResolvers = null;  if (this.detectAllViewResolvers) {   // Find all ViewResolvers in the ApplicationContext, including ancestor contexts.   Map<String, ViewResolver> matchingBeans =     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);   if (!matchingBeans.isEmpty()) {    this.viewResolvers = new ArrayList<>(matchingBeans.values());    // We keep ViewResolvers in sorted order.    AnnotationAwareOrderComparator.sort(this.viewResolvers);   }  }  else {   try {    ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);    this.viewResolvers = Collections.singletonList(vr);   }   catch (NoSuchBeanDefinitionException ex) {    // Ignore, we'll add a default ViewResolver later.   }  }  // Ensure we have at least one ViewResolver, by registering  // a default ViewResolver if no other resolvers are found.  if (this.viewResolvers == null) {   this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);   if (logger.isTraceEnabled()) {    logger.trace("No ViewResolvers declared for servlet '" + getServletName() +      "': using default strategies from DispatcherServlet.properties");   }  } }

一开始的 viewResolvers 变量是一个集合,解析出来的视图解析器对象都将放入这个集合中。

首先判断 detectAllViewResolvers 变量是否为 true,如果为 true,则直接去查找 Spring  容器中的所有视图解析器,将查找结果赋值给 viewResolvers,然后进行排序。默认情况下 detectAllViewResolvers 变量的值为  true,如果有需要,可以在 web.xml 中进行配置,像下面这样:

<servlet>     <servlet-name>springmvc</servlet-name>     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>     <init-param>         <param-name>contextConfigLocation</param-name>         <param-value>classpath:spring-servlet.xml</param-value>     </init-param>     <init-param>         <param-name>detectAllViewResolvers</param-name>         <param-value>false</param-value>     </init-param>     <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping>     <servlet-name>springmvc</servlet-name>     <url-pattern>/</url-pattern> </servlet-mapping>

如果 detectAllViewResolvers 的值为 false,那么接下来就会去 Spring 容器中查找一个名为 viewResolver  的视图解析器,此时查找到的就是一个单独的视图解析器。

一般来说,我们并不需要在 web.xml 中去配置 detectAllViewResolvers 的值,视图解析器有多少个就加载多少个。

举个简单例子,我们在 SpringMVC 的配置文件中可能像下面这样配置视图解析器:

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

默认情况下,这个 bean 的 id 有没有都行,如果有,取什么值都可以,反正最终都是通过类型而不是 id 去查找的视图解析器。但是如果你在  web.xml 中将 detectAllViewResolvers 修改为 false,那么这个 bean 的 id 取值就比较重要了,就一定要是  viewResolver。

如果在 Spring 容器中通过这两种方式(通过类型查找或通过 id 查找)都没有找到 ViewResolver 实例,那么会调用  getDefaultStrategies 方法去获取一个默认的 ViewResolver 实例。默认实例的获取方式如下:

protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {  if (defaultStrategies == null) {   try {    // Load default strategy implementations from properties file.    // This is currently strictly internal and not meant to be customized    // by application developers.    ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);    defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);   }   catch (IOException ex) {    throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());   }  }  String key = strategyInterface.getName();  String value = defaultStrategies.getProperty(key);  if (value != null) {   String[] classNames = StringUtils.commaDelimitedListToStringArray(value);   List<T> strategies = new ArrayList<>(classNames.length);   for (String className : classNames) {    try {     Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());     Object strategy = createDefaultStrategy(context, clazz);     strategies.add((T) strategy);    }    catch (ClassNotFoundException ex) {     throw new BeanInitializationException(       "Could not find DispatcherServlet's default strategy class [" + className +       "] for interface [" + key + "]", ex);    }    catch (LinkageError err) {     throw new BeanInitializationException(       "Unresolvable class definition for DispatcherServlet's default strategy class [" +       className + "] for interface [" + key + "]", err);    }   }   return strategies;  }  else {   return Collections.emptyList();  } }

这段代码其实也比较简单,就是通过反射去获取默认的视图解析器。

首先给 defaultStrategies 赋值,defaultStrategies 的值实际上就是从  DispatcherServlet.properties 文件中加载到的,我们来看下这个文件内容:

SpringMVC初始化流程是什么

可以看到,这里一共定义了 8 个默认的键值对,有的值是一个,有的值是多个。前面 initStrategies 方法中一共要初始化九个组件,这里默认只定义了  8 个,少了一个 MultipartResolver,这也好理解,并非所有的项目都有文件上传,而且即使有文件上传,用哪一个具体的  MultipartResolver 也不好确定,还是要开发者自己决定。

defaultStrategies 其实加载到的就是这 8 个键值对,其中视图解析器对应的是  org.springframework.web.servlet.view.InternalResourceViewResolver,通过反射创建该类的实例,当  Spring 容器中不存在任何视图解析器的时候,默认的视图解析器即此。

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

private void initMultipartResolver(ApplicationContext context) {  try {   this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);  }  catch (NoSuchBeanDefinitionException ex) {   this.multipartResolver = null;  } }

可以看到,它只是根据 bean 的名字去查找 bean 实例,没有去查找默认的 MultipartResolver。

说到这里,松哥和大家多说一句 SpringMVC 配置中的小细节,

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

上面这个关于视图解析器和文件上传解析器的配置,不知道小伙伴们有没有注意过,视图解析器的 id 可有可无,而文件上传解析器的 id 必须是  multipartResolver,回顾我们上面的源码分析,你就知道为啥了!

到此,相信大家对“SpringMVC初始化流程是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: SpringMVC初始化流程是什么

本文链接: https://www.lsjlt.com/news/83389.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringMVC初始化流程是什么
    本篇内容主要讲解“SpringMVC初始化流程是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringMVC初始化流程是什么”吧!框架源码是我们 Cod...
    99+
    2022-10-19
  • 深入了解SpringMVC初始化流程
    目录前言1.HttpServletBean2.FrameworkServlet3.DispatcherServlet4.小结前言 框架源码是我们 Coding 晋级中的必修课,SSM...
    99+
    2022-11-13
  • SpringMVC初始化流程实例分析
    本文小编为大家详细介绍“SpringMVC初始化流程实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringMVC初始化流程实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.HttpServl...
    99+
    2023-07-02
  • Vue Router中Matcher的初始化流程是什么
    这篇文章主要讲解了“Vue Router中Matcher的初始化流程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue Router中Matcher的初始化流程是...
    99+
    2023-06-30
  • Flutter初始化流程是怎样的
    本篇内容介绍了“Flutter初始化流程是怎样的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Flutter初始化时序Flutter初始化主...
    99+
    2023-06-04
  • java什么是初始化?
    java什么是初始化?初始化就是给变量一个初始值。初始化的目的是为了让变量有值,防止使用时出现异常。【推荐学习:java课程】例如:声明一个变量:String aa = "abc"; int cc =0;其中abc和0就是初始化的值,最后值...
    99+
    2018-07-08
    java教程 java 初始化
  • java什么是初始化
    java什么是初始化初始化就是给变量一个初始值。例如:声明一个变量:String php = "www.php.cn"; int score = 100; 其中 www.php.cn 和 100 就是初始化的值,最后值不一定是 www.p...
    99+
    2016-01-15
    java基础 java 初始化
  • Spring Security基本架构与初始化操作流程是什么
    这篇文章主要介绍“Spring Security基本架构与初始化操作流程是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring Security基本架构与初始化操作流程...
    99+
    2023-07-05
  • 什么是Java的初始化
    初始化就是给变量一个初始值。例如:声明一个变量:String aa = "abc";int cc =0;其中abc和0就是初始化的值,最后值不一定是abc或者0加入你覆盖了aa的值如下:aa = "def" ; cc=1;那最后aa变量的值...
    99+
    2015-08-08
    java入门 Java 初始化
  • Java类的初始化过程是什么
    Java类的初始化过程包括以下几个步骤: 加载类:当程序中使用到某个类时,Java虚拟机会先通过类加载器将该类的字节码文件加载到...
    99+
    2023-10-26
    java
  • Vue Router中Matcher的初始化流程
    目录MatchercreateMatcher()的初始化1、Location类型2、rowLocation类型3、Route类型4、RouteRecord类型addRoutes()的...
    99+
    2022-11-13
  • Spring WebMVC初始化Controller流程详解
    目录SpringWebMVC初始化Controller流程获取容器初始化的所有beanName(父子容器概念)获取所有声明为Controller类的beanName开始处理这种类型的...
    99+
    2022-11-13
  • 初始化vue项目的过程 是什么
    本篇内容主要讲解“初始化vue项目的过程 是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“初始化vue项目的过程 是什么”吧!在命令行执行命令“vue init webpack vue-pr...
    99+
    2023-07-05
  • Git初始化命令是什么
    这篇文章给大家分享的是有关Git初始化命令是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 初始化命令命令作用git init初始化 git,创建 .git 文件感...
    99+
    2022-10-19
  • Vue初始化是什么意思
    Vue 是一款非常流行的 JavaScript 框架,广泛用于构建现代化的 Web 应用程序。在开始学习 Vue 之前,你需要先了解 Vue 的初始化过程,以便正确地使用 Vue 并创建可重复的代码。初始化 Vue 是指在页面中创建一个 V...
    99+
    2023-05-14
  • css初始化是什么意思
    这篇文章给大家分享的是有关css初始化是什么意思的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。CSS初始化是指重设浏览器的样式。不同的浏览器默认的样式可能不尽相同,所以开发时的第一件事可能就是如何把它们统一。如果...
    99+
    2023-06-14
  • Java类初始化执行流程解析
     测试代码:   package com.test.ClassLaoderTest; public class test1 { public static Strin...
    99+
    2022-11-12
  • Android中初始化Codec2的具体流程
    目录1、MediaCodec调用流程2、CCodec调用流程小结:3、整体时序图1、MediaCodec调用流程 首先,我们先看下MediaCodec::CreateByType函数...
    99+
    2022-11-12
  • VueRouter 原理解读之初始化流程
    目录1.1 核心概念官方介绍使用与阅读源码的必要性1.2 基本使用路由配置与项目引入路由组件使用跳转 api 调用2.1 createRouter 初始化入口分析大致流程Router...
    99+
    2023-05-19
    VueRouter 初始化原理  VueRouter 初始化
  • Mybatis SqlSessionFactory初始化原理是什么
    这篇文章主要讲解了“Mybatis SqlSessionFactory初始化原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Mybatis SqlSessionFactory初始化原...
    99+
    2023-06-20
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作