• 技术文章 >Java >java教程

    分析spring web启动时IOC源码

    高洛峰高洛峰2017-03-12 09:40:08原创551
    这篇文章分析spring web启动时IOC源码研究

    1. 研究IOC首先创建一个简单的web项目,在web.xml中我们都会加上这么一句

    <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </context-param>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

    这代表了web容器启动的时候会首先进入ContextLoaderListener这个类,并且之后会去加载classpath下的applicationContext.xml文件。那么重点就在ContextLoaderListener上,点开源码:

    /**
         * Initialize the root web application context.     */
        @Override    public void contextInitialized(ServletContextEvent event) {
            initWebApplicationContext(event.getServletContext());
        }    /**
         * Close the root web application context.     */
        @Override    public void contextDestroyed(ServletContextEvent event) {
            closeWebApplicationContext(event.getServletContext());
            ContextCleanupListener.cleanupAttributes(event.getServletContext());
        }

    里面主要为ServletContextListener接口的两个实现方法。web容器会首先调用contextInitialized方法,传入tomcat封装的容器资源,之后调用父类的初始化容器方法。

    /*** The root WebApplicationContext instance that this loader manages.*/private WebApplicationContext context;public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
          ...........省略// 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);
                }
      ......省略            return this.context;
            
        }

    这个方法里主要步骤createWebApplicationContext方法用来创建XmlWebApplicationContext这个root根容器,这个容器就是取自servletContextEvent。

    loadParentContext方法用来加载父容器。主要方法configureAndRefreshWebApplicationContext用来配置和刷新root容器,在方法内最主要的就是refresh方法,里面实现了最主要的功能。

    @Override    public void refresh() throws BeansException, IllegalStateException {        synchronized (this.startupShutdownMonitor) {            // Prepare this context for refreshing.            prepareRefresh();            // Tell the subclass to refresh the internal bean factory.
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();            // Prepare the bean factory for use in this context.            prepareBeanFactory(beanFactory);            try {                // Allows post-processing of the bean factory in context subclasses.                postProcessBeanFactory(beanFactory);                // Invoke factory processors registered as beans in the context.                invokeBeanFactoryPostProcessors(beanFactory);                // Register bean processors that intercept bean creation.                registerBeanPostProcessors(beanFactory);                // Initialize message source for this context.                initMessageSource();                // Initialize event multicaster for this context.                initApplicationEventMulticaster();                // Initialize other special beans in specific context subclasses.                onRefresh();                // Check for listener beans and register them.                registerListeners();                // Instantiate all remaining (non-lazy-init) singletons.                finishBeanFactoryInitialization(beanFactory);                // Last step: publish corresponding event.                finishRefresh();
                }            catch (BeansException ex) {
                    logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);                // Destroy already created singletons to avoid dangling resources.                destroyBeans();                // Reset 'active' flag.                cancelRefresh(ex);                // Propagate exception to caller.
                    throw ex;
                }
            }
        }

    prepareRefresh方法用来准备之后需要用到的环境。

    obtainFreshBeanFactory方法获取beanFactory

    @Override    protected final void refreshBeanFactory() throws BeansException {        if (hasBeanFactory()) {
                destroyBeans();
                closeBeanFactory();
            }        try {
                DefaultListableBeanFactory beanFactory = createBeanFactory();
                beanFactory.setSerializationId(getId());
                customizeBeanFactory(beanFactory);
                loadBeanDefinitions(beanFactory);            synchronized (this.beanFactoryMonitor) {                this.beanFactory = beanFactory;
                }
            }        catch (IOException ex) {            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
            }
        }

    实际返回的beanFactory为其实现类DefaultListableBeanFactory,实例化该类用来为之后装载xml中实例化的类。

    loadBeanDefinitions为重要的方法,用来真正的加载类了,之前的都是准备工作

    以上就是分析spring web启动时IOC源码的详细内容,更多请关注php中文网其它相关文章!

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    专题推荐:spring web
    上一篇:图文Java之Junit入门案例(代码) 下一篇:使用java.nio.charset.CharsetDecoder自动识别字符集方法
    大前端线上培训班

    相关文章推荐

    • 理解java8中java.util.function.*pojo反射新方法(附代码)• 浅析安卓app和微信授权登录及分享完整对接(代码分享)• 教你一招搞定时序数据库在Spring Boot中的使用• 一招教你使用java快速创建Map(代码分享)• PlayFramework 完整实现一个APP(十一)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网