【JavaEE学习贴3】分析spring webmvc启动流程——IoC容器创建、bean初始化

概念

IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IOC容器进行组装。

Spring提供一个最为基础的IoC容器——BeanFactory,但这个IoC容器所能提供给的功能比较少,所以我们通常选用另一个——ApplicationContext(应用上下文)来作为IoC容器。ApplicationContext也是继承自BeanFactory,只是在BeanFactory接口基础上做了扩展。

web.xml中

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

这段配置意为给Servlet新增一个监听器,这个监听器需要实现ServletContextListener接口。

public interface ServletContextListener extends EventListener {
    
    
    void contextInitialized(ServletContextEvent var1);

    void contextDestroyed(ServletContextEvent var1);
}

再来看看ContextLoaderListener,WebApplicationContext的初始化实际上是由ContextListener完成的。

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    
    
    public ContextLoaderListener() {
    
    
    }

    public ContextLoaderListener(WebApplicationContext context) {
    
    
        super(context);
    }

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

    public void contextDestroyed(ServletContextEvent event) {
    
    
        this.closeWebApplicationContext(event.getServletContext());
        ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }
}

public void initWebApplicationContext(ServletContext servletContext)

public void initWebApplicationContext(ServletContext servletContext) 
    ......
    if(this.context == null) {
    
    
        this.context = this.createWebApplicationContext(servletContext);    //创建根上下文,在这之前会检查是否已经存在,如果存在则抛出IllegalStateExcpetion异常,跳到第22行
    }
    ......
    if(this.context instanceof ConfigurableWebApplicationContext) {
    
        
        ConfigurableWebApplicationContext err = (ConfigurableWebApplicationContext)this.context;
        if(!err.isActive()) {
    
    
            if(err.getParent() == null) {
    
    
                ApplicationContext elapsedTime = this.loadParentContext(servletContext);
                err.setParent(elapsedTime);
            }
        this.configureAndRefreshWebApplicationContext(err, servletContext);    //ApplicationContext上下文创建好后对其进行赋值和初始化,跳到第31行
        }
    }
    //将WebApplicationContext根上下文绑定到Web应用程序的ServletContext上.
    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
    .....
     return this.context;
}
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
    
    
    Class contextClass = this.determineContextClass(sc);    //判断使用什么样的类在Web容器中作为IoC容器,跳到第26行
    ......
}
protected Class<?> determineContextClass(ServletContext servletContext) {
    
    
    String contexClassName = servlet.getInitParameter(CONTEXT_CLASS_PARAM);    //读取web.xml中的配置<context-param>contextClass</context-param>
    //如果配置了需要使用的CONTEXT_CLASS,那就是用这个class,如果没有额外的配置,就是用默认的ContextClass也就是XmlWebApplicationContext.
}
//设置IoC容器的参数,并通过refresh启动容器的初始化
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc){
    
    
    String configLocationParam;
if(ObjectUtils.identityToString(wac).equals(wac.getId())) {
    
    
    configLocationParam = sc.getInitParameter("contextId");
    if(configLocationParam != null) {
    
    
        wac.setId(configLocationParam);
    } else {
    
    
        wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
    }
}
    wac.setServletContext(sc);
    configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);    //contextConfigLocation,Spring根应用上下文重要的配置文件,很多bean的定义等等
    ......
    wac.refresh();    //启动容器的初始化
}

指定了web.xml的配置的指定IoC容器

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

applicationContext.xml中则定义了bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="JDBC" class="jdbc.StudentHomeworkJdbc" xml:id="JDBC1"></bean>
    <bean id="pool" class="jdbc.DatabasePool" xml:id="pool1"></bean>
</beans>

通过这样的方式则可以创建实例

ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
StudentHomeworkJdbc jdbc=(StudentHomeworkJdbc)applicationContext.getBean("JDBC");
jdbc.addHomework(homework);

猜你喜欢

转载自blog.csdn.net/Shadownow/article/details/105534478