您的位置:首页 > 编程语言 > Java开发

SPRING 启动加载BEAN 的代码过程

2017-08-11 15:14 323 查看
当Web应用启动时,contextInitialized方法会执行载入根上下文(IOC容器):

(1)spring的web项目启动的时候会,启动我们常用的监听类。

      <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/classes/spring-context.xml</param-value>
</context-param>
<!-- Spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

(2)tomcat在加载web应用时候,会针对每个web.xml的监听器进行创建,看org.apache.catalina.core.StandardContext.listenerStart(),

public
boolean listenerStart() {

    if (log.isDebugEnabled())

        log.debug("Configuring application event listeners");

    String listeners[] = findApplicationListeners();

    Object results[] = new Object[listeners.length];

    boolean ok = true;

    for (int i = 0; i < results.length; i++) {

        if (getLogger().isDebugEnabled())

            getLogger().debug(" Configuring event listener class '" + listeners[i] + "'");

        try {

            String listener = listeners[i];

            results[i] = getInstanceManager().newInstance(listener);

        } catch (Throwable t) {

            t = ExceptionUtils.unwrapInvocationTargetException(t);

            ExceptionUtils.handleThrowable(t);

            getLogger().error(sm.getString("standardContext.applicationListener", listeners[i]), t);

            ok = false;

        }

    }

    if (!ok) {

        getLogger().error(sm.getString("standardContext.applicationSkipped"));

        return (false);

    }

    ArrayList<Object> eventListeners = new ArrayList<>();

    ArrayList<Object> lifecycleListeners = new ArrayList<>();

    for (int i = 0; i < results.length; i++) {

        if ((results[i] instanceof ServletContextAttributeListener)

                || (results[i] instanceof ServletRequestAttributeListener)

                || (results[i] instanceof ServletRequestListener)

                || (results[i] instanceof HttpSessionIdListener)

                || (results[i] instanceof HttpSessionAttributeListener)) {

            eventListeners.add(results[i]);

        }

        if ((results[i] instanceof ServletContextListener)

                || (results[i] instanceof HttpSessionListener)) {

            lifecycleListeners.add(results[i]);

        }

    }

    for (Object eventListener : getApplicationEventListeners()) {

        eventListeners.add(eventListener);

    }

    setApplicationEventListeners(eventListeners.toArray());

    

    for (Object lifecycleListener : getApplicationLifecycleListeners()) {

        lifecycleListeners.add(lifecycleListener);

        if (lifecycleListener instanceof ServletContextListener) {

            noPluggabilityListeners.add(lifecycleListener);

        }

    }

    setApplicationLifecycleListeners(lifecycleListeners.toArray());

    if (getLogger().isDebugEnabled())

        getLogger().debug("Sending application start events");

    getServletContext();

    context.setNewServletContextListenerAllowed(false);

    Object instances[] = getApplicationLifecycleListeners();

    if (instances == null || instances.length == 0) {

        return ok;

    }

    ServletContextEvent
event = new ServletContextEvent(getServletContext());

    ServletContextEvent tldEvent = null;

    if (noPluggabilityListeners.size() > 0) {

        noPluggabilityServletContext = new NoPluggabilityServletContext(getServletContext());

        tldEvent = new ServletContextEvent(noPluggabilityServletContext);

    }

    for (int i = 0; i < instances.length; i++) {

        if (!(instances[i] instanceof ServletContextListener))

            continue;

        ServletContextListener listener = (ServletContextListener) instances[i];

        try {

            fireContainerEvent("beforeContextInitialized", listener);

            if (noPluggabilityListeners.contains(listener)) {

                listener.contextInitialized(tldEvent);

            } else {

                listener.contextInitialized(event); 

            }
            fireContainerEvent("afterContextInitialized", listener);//注册事件
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            fireContainerEvent("afterContextInitialized", listener);
            getLogger().error(sm.getString("standardContext.listenerStart", instances[i].getClass().getName()), t);
            ok = false;
        }
    }
    return (ok);
}

(3)具体的创建wepapplicationcontext的过程如下:

ContextLoaderListener.contextInitialized(ServletContextEvent event) 

 

->ContextLoader.initWebApplicationContext(ServletContext servletContext) 

 

->ContextLoader.createWebApplicationContext(ServletContext sc) - - - - - 如果web.xml里没指定类型,默认是XmlWebAppalication

 

->ContextLoader.configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc)  - - - - - -  配置和初始化 webApplicationContext

 

->ConfigurableWebApplicationContext.refresh() - - - - -  ConfigurableWebApplicationContext是接口

 

->AbstractApplicationContext.refresh() - - - - - 启动 容器初始化

 

->AbstractApplicationContext.obtainFreshBeanFactory() - - - - -  创建BeanFactory,开始容器的初始化过程,比如BeanDefinition的载入

 

->AbstractRefreshableApplicationContext.refreshBeanFactory() - - - - - 在这里创建了BeanFactory(DefaultListableBeanFactory)。然后开始loadBeanDefinitions,这是一个抽象方法,实际的载入是在XmlWebApplicationContext类里。

 

->XmlWebApplicationContext.loadBeanDefinitions(DefaultListableBeanFactory beanFactory) - - - -创建一个XmlBeanDefinitionReader,并启动bean定义信息的载入。

 

->XmlWebApplicationContext.loadBeanDefinitions(XmlBeanDefinitionReader reader) - - - 根据配置文件的locations,因为配置文件是xml的,所以使用的是XmlBeanDefinitionReader 。具体的载入过程是委托给BeanDefinitionReader完成的

 

->AbstractBeanDefinitionReader.loadBeanDefinitionReader - - - 这是一个抽象类,实际的载入是在XmlBeanDefinitionReader中实现的,抽象类是根据bean定义的xml配置文件的路径,生成resource。然后XmlBeanDefinitionReader根据resource开始具体载入BeanDefinition

 

->XmlBeanDefinitionReader.loadBeanDefinitionReader(Resource resource)

 

->XmlBeanDefinitionReader.loadBeanDefinitions(EncodedResource encodedResource) - - - 在读取器中,需要得到代表XML文件的resource,这个resource对象封装了对xml文件的IO操作,所以读取器可以在打开IO流后得到XML的文件对象。

 

->XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource) - - - -读取器在这里打开IO流后得到XML的文件Document对象(Document对象是通过XML解析器出来的,下面会再根据Spring Bean的规则再解析出BeanDefinition)。得到对象后就可以按照spring的Bean定义规则来对这个xml的文件档树进行解析了

 

->XmlBeanDefinitionReader.registerBeanDefinitions(Document doc, Resource resource) - - -这个方法启动对BeanDefinition的解析的详细过程,这个解析会使用到Spring的Bean的配置规则。具体的过程是有BeanDefinitionDocumentReader来完成的。

->BeanDefinitionDocumentReader.registerBeanDefinitions(Document doc, XmlReaderContext readerContext)

 

->DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(Document doc, XmlReaderContext readerContext) - - - - -DefaultBeanDefinitionDocumentReader 是BeanDefinitionDocumentReader的实现类,registerBeanDefinitions方法开始按照Spring
Bean的规则解析Document对象

 

->DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root) - - -解析过程是由BeanDefinitionParserDelegate对象来完成的。

 

->DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) 

->DefaultBeanDefinitionDocumentReader.parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)

->DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
 - - - - 解析的结果是由BeanDefinitionHolder来持有的,这个BeanDefinitionHolder对象封装了BeanDefinition,beanName,aliases等信息,用它来完成向IOC容器注册。

 

->BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element ele) 

->BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)

->BeanDefinitionParserDelegate.parseBeanDefinitionElement(

               Element ele, String beanName, BeanDefinition containingBean) - - - 对xml配置文件中的配置的Bean进行详细解析,这里只是读取定义 的<bean>,并载入到BeanDefinition中去,这里不涉及对象的实例化过程,对象的实例化实际上是再依赖注入时完成的。
 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: