软件编程
位置:首页>> 软件编程>> java编程>> java Spring的启动原理详解

java Spring的启动原理详解

作者:Java技术债务  发布时间:2022-09-02 04:39:59 

标签:spring,java,启动原理

引入

为什么突然说一下Spring启动原理呢,因为之前面试的时候,回答的那可谓是坑坑洼洼,前前后后,补补贴贴。。。

总而言之就是不行,再次看一下源码发掘一下。。。

在Spring Boot还没有广泛到家家在用的时候,我们都还在书写繁琐的配置,什么web.xml、spring.xml、bean.xml等等。虽然现在很少,可以说几乎没有企业在去使用Spring的老一套,而会去使用Spring Boot约定大于配置来进行快速开发,但是,Spring的也要去学习,去挖掘,毕竟是我们Java程序员的基础呀。

spring的启动是建筑在servlet容器之上的,所有web工程的初始位置就是web.xml,它配置了servlet的上下文(context)和 * (Listener)

web.xml

<!--上下文 * ,用于监听servlet的启动过程-->
   <listener>
       <description>ServletContextListener</description>
       <!--这里是自定义 * ,个性化定制项目启动提示-->
       <listener-class>com.trace.app.framework.listeners.ApplicationListener</listener-class>
   </listener>
   <!--dispatcherServlet的配置,这个servlet主要用于前端控制,这是springMVC的基础-->
   <servlet>
       <servlet-name>service_dispatcher</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>/WEB-INF/spring/services/service_dispatcher-servlet.xml</param-value>
       </init-param>
       <load-on-startup>1</load-on-startup>
   </servlet>
   <!--spring资源上下文定义,在指定地址找到spring的xml配置文件-->
   <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>/WEB-INF/spring/application_context.xml</param-value>
   </context-param>
   <!--spring的上下文 * -->
   <listener>
       <listener-class>
           org.springframework.web.context.ContextLoaderListener
       </listener-class>
   </listener>
   <!--Session * ,Session作为公共资源存在上下文资源当中,这里也是自定义 * -->
   <listener>
       <listener-class>
           com.trace.app.framework.listeners.MySessionListener
       </listener-class>
   </listener>

Spring启动过程

spring的上下文 *

<context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>/WEB-INF/spring/application_context.xml</param-value>
</context-param>

<listener>
       <listener-class>
           org.springframework.web.context.ContextLoaderListener
       </listener-class>
</listener>

spring的启动其实就是IOC容器的启动过程,通过上述的第一段配置 <context-param> 是初始化上下文,然后通过后一段的的<listener>来加载配置文件,其中调用的spring包中的ContextLoaderListener这个上下文 * ,ContextLoaderListener是一个实现了ServletContextListener接口的 * ,他的父类是 ContextLoader,在启动项目时会触发contextInitialized上下文初始化方法。

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

调用了父类ContextLoader的initWebApplicationContext(event.getServletContext());方法,很显然,这是对ApplicationContext的初始化方法,也就是到这里正是进入了springIOC的初始化。

接下来看一下initWebApplicationContext(event.getServletContext())的工作:

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!");
       }

Log logger = LogFactory.getLog(ContextLoader.class);
       servletContext.log("Initializing Spring root WebApplicationContext");
       if (logger.isInfoEnabled()) {
           logger.info("Root WebApplicationContext: initialization started");
       }
       long startTime = System.currentTimeMillis();

try {
           // Store context in local instance variable, to guarantee that
           // it is available on ServletContext shutdown.
           if (this.context == null) {
               this.context = createWebApplicationContext(servletContext);
           }
           if (this.context instanceof ConfigurableWebApplicationContext) {
               ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
               if (!cwac.isActive()) {
                   // The context has not yet been refreshed -> provide services such as
                   // setting the parent context, setting the application context id, etc
                   if (cwac.getParent() == null) {
                       // The context instance was injected without an explicit parent ->
                       // determine parent for root web application context, if any.
                       ApplicationContext parent = loadParentContext(servletContext);
                       cwac.setParent(parent);
                   }
                   configureAndRefreshWebApplicationContext(cwac, servletContext);
               }
           }
           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);
           }

if (logger.isDebugEnabled()) {
               logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
                       WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
           }
           if (logger.isInfoEnabled()) {
               long elapsedTime = System.currentTimeMillis() - startTime;
               logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
           }

return this.context;
       }
       catch (RuntimeException ex) {
           logger.error("Context initialization failed", ex);
           servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
           throw ex;
       }
       catch (Error err) {
           logger.error("Context initialization failed", err);
           servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
           throw err;
       }

总结:

创建WebApplicationContext。加载对应的spring配置文件中的Bean。将WebApplicationContext放入ServletContext(Java Web的全局变量)中。

接下来,来到了configureAndRefreshWebApplicationContext()方法

作用:

就是用来加载spring配置文件中的Bean实例的。这个方法于封装ApplicationContext数据并且初始化所有相关Bean对象。它会从web.xml中读取名为 contextConfigLocation的配置,这就是spring xml数据源设置,然后放到ApplicationContext中,最后调用传说中的refresh方法执行所有Java对象的创建。

总结:

java Spring的启动原理详解

来源:https://blog.csdn.net/qq_40124555/article/details/122732849

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com