博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
webx3.0-容器初始化
阅读量:5838 次
发布时间:2019-06-18

本文共 20535 字,大约阅读时间需要 68 分钟。

hot3.png

概念介绍

Contexts

WebxComponentsContext

----类介绍:所有组件的共有上下文,即父容器,对应的默认spring配置文件为“webx.xml”

----成员变量

WebxComponentsLoader:因为beanFactory的行为均定义在WebxComponentsLoader中,故持有此变量

----成员函数

getWebxComponents:从加载器中取得webxComponents

postProcessBeanFactory:拓展点之一,使用该拓展点旨在合理的时间内创建compone nts和component

finishRefresh:拓展点之一,使用该拓展点旨在合理的时间内refresh组件的beanFactory

WebxComponentContext

---类介绍:组件的上下文,对应的默认spring配置文件为"webx*.xml"

----成员变量

WebxComponent:组件

Components

WebxComponentsImpl

----成员变量

parentConfiguration:父容器的配置,对应于“webx.xml”中"name"为"webx_configuration"的bean,这是一个VO

parentContext:即父容器

components:一个map,保存所有的component的映射

rootComponent:根组件,对应的context即parentContext

defaultComponentName:默认组件名,根据"webx_configuration"得出

rootController:父组件的控制器

RootComponent

TODO

WebxComponent

----成员变量

components:持有所属的conponents

name:组件名

componentPath:组件路径

controller:组件的控制器

webxConfiurationName:为了获取各组件configuration的bean的name

context:顾名思义,即各个组件的上下文

Controllers

TODO

Configurations

TODO

初始化概述

1、servlet容器启动

web.xml:

     
        
loggingRoot
        
/Users/apple/workspace/3.0/petstore/logs
    
    
        
loggingLevel
        
warn
    
    
        
loggingCharset
        
UTF-8
    
     
        
com.alibaba.citrus.logconfig.LogConfiguratorListener
    
     
    
        
com.alibaba.citrus.webx.context.WebxContextLoaderListener
    
     
        
mdc
        
com.alibaba.citrus.webx.servlet.SetLoggingContextFilter
    
     
        
webx
        
com.alibaba.citrus.webx.servlet.WebxFrameworkFilter
    
     
        
mdc
        
/*
    
     
        
webx
        
/*
    
     
        
index.html
        
index.jsp
    
 

在这里,WebxContextLoaderListener负责框架的初始化,而WebxFrameworkFilter则是框架的入口

2、实例化加载器ContextLoader

重写了spring提供的加载器,应用WebxComponentsLoader,充血模型,定义了大多数的行为

3、加载ComponentsContext

对应的配置文件为"webx.xml",为所有组件context的父容器

4、加载Components,Component,ComponentsController,ComponentController

通过spring的拓展点postProcessBeanFactory植入了创建components的bean,在后续的invoke中执行该bean的post方法

5、初始化单例Bean

ApplicationContext的特点之一

6、初始化ComponentsController

通过spring的事件监听机制,注册Components观察者,实现成员变量ComponetsController的初始化

7、初始化Component

通过spring容器的finishRefresh拓展实现组件的初始化

8、初始化ComponentController

依旧通过观察者模式利用spring的事件监听机制实现pipeline等的初始化

9、初始化FilterChain

至此bean容器初始化完成,接下来初始化FilterChain的每个filter,这里将从servletContext取出上一步骤生成的Components等参数来初始化filter

初始化详解

从initWebApplicationContext入口点开始

【ContextLoader】public WebApplicationContext initWebApplicationContext(ServletContext servletContext)            throws IllegalStateException, BeansException {         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!");        }         servletContext.log("Initializing Spring root WebApplicationContext");        if (logger.isInfoEnabled()) {            logger.info("Root WebApplicationContext: initialization started");        }        long startTime = System.currentTimeMillis();         try {            // Determine parent for root web application context, if any.            ApplicationContext parent = loadParentContext(servletContext);             // Store context in local instance variable, to guarantee that            // it is available on ServletContext shutdown.            this.context = createWebApplicationContext(servletContext, parent);            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);            currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);             ......

接下来看下CreateWebApplicationContext,这里有个拓展点

【ContextLoader】protected WebApplicationContext createWebApplicationContext(            ServletContext servletContext, ApplicationContext parent) throws BeansException {         Class contextClass = determineContextClass(servletContext);        if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {            throw new ApplicationContextException("Custom context class [" + contextClass.getName() +                    "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");        }         ConfigurableWebApplicationContext wac =                (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);        wac.setParent(parent);        wac.setServletContext(servletContext);        wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));        customizeContext(servletContext, wac);        wac.refresh();         return wac;    }
【WebxComponentsLoader】protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext componentsContext) {        this.componentsContext = componentsContext;         if (componentsContext instanceof WebxComponentsContext) {            ((WebxComponentsContext) componentsContext).setLoader(this);        }    }

了解下refresh做了哪些事

【AbstractContextApplication】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) {                // Destroy already created singletons to avoid dangling resources.                beanFactory.destroySingletons();                 // Reset 'active' flag.                cancelRefresh(ex);                 // Propagate exception to caller.                throw ex;            }        }    }

有几个步骤比较重要依次介绍下,先看postProcessBeanFactory这一步

【WebxComponentsContext】protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {        super.postProcessBeanFactory(beanFactory);        getLoader().postProcessBeanFactory(beanFactory);    }

这里已经可以看到webxComponentsContext持有loader是为了调用loader的行为;

【WebxComponentsLoader】public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {        // 由于初始化components依赖于webxConfiguration,而webxConfiguration可能需要由PropertyPlaceholderConfigurer来处理,        // 此外,其它有一些BeanFactoryPostProcessors会用到components,        // 因此components必须在PropertyPlaceholderConfigurer之后初始化,并在其它BeanFactoryPostProcessors之前初始化。        //        // 下面创建的WebxComponentsCreator辅助类就是用来确保这个初始化顺序:        // 1. PriorityOrdered - PropertyPlaceholderConfigurer        // 2. Ordered - WebxComponentsCreator        // 3. 普通 - 其它BeanFactoryPostProcessors        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(WebxComponentsCreator.class);        builder.addConstructorArgValue(this);        BeanDefinition componentsCreator = builder.getBeanDefinition();        componentsCreator.setAutowireCandidate(false);         BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;        String name = SpringExtUtil.generateBeanName(WebxComponentsCreator.class.getName(), registry);         registry.registerBeanDefinition(name, componentsCreator);    }

接下来就是执行这些BeanFactoryProcessor,个人觉得这个需要深入研究下

【AbstractApplicationContext】protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {        // Invoke factory processors registered with the context instance.        for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {            BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();            factoryProcessor.postProcessBeanFactory(beanFactory);        }         // Do not initialize FactoryBeans here: We need to leave all regular beans        // uninitialized to let the bean factory post-processors apply to them!        String[] postProcessorNames =                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);         // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,        // Ordered, and the rest.        List priorityOrderedPostProcessors = new ArrayList();        List orderedPostProcessorNames = new ArrayList();        List nonOrderedPostProcessorNames = new ArrayList();        for (int i = 0; i < postProcessorNames.length; i++) {            if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {                priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));            }            else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {                orderedPostProcessorNames.add(postProcessorNames[i]);            }            else {                nonOrderedPostProcessorNames.add(postProcessorNames[i]);            }        }         // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.        Collections.sort(priorityOrderedPostProcessors, new OrderComparator());        invokeBeanFactoryPostProcessors(beanFactory, priorityOrderedPostProcessors);         ......

这里有两个看点:1、BeanFactory第一次初始化Bean貌似就是这里,当然这个是题外话;2、一共有3个Bean需要被post,第一个是占位符(在webx.xml配置了该bean),第二个是RequestContextBeanFactoryPostProcessor,第三个是WebxComponentsCreator。主要分析后面两个,第一个是现存的,不做分析。

WebxComponentsCreator

【WebxComponentsLoader】public static class WebxComponentsCreator implements BeanFactoryPostProcessor, Ordered {        private final WebxComponentsLoader loader;         public WebxComponentsCreator(WebxComponentsLoader loader) {            this.loader = assertNotNull(loader, "WebxComponentsLoader");        }         public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {            if (loader.components == null) {        //loader.getParentConfiguration()为第一次执行getBean操作,configuration是什么,下面有分析                WebxComponentsImpl components = loader.createComponents(loader.getParentConfiguration(), beanFactory);                AbstractApplicationContext wcc = (AbstractApplicationContext) components.getParentApplicationContext();                wcc.addApplicationListener(new SourceFilteringListener(wcc, components));                loader.components = components;            }        }  private WebxComponentsImpl createComponents(WebxConfiguration parentConfiguration,                                                ConfigurableListableBeanFactory beanFactory) {    //从VO中取出Bean        ComponentsConfig componentsConfig = getComponentsConfig(parentConfiguration);         // 假如isAutoDiscoverComponents==true,试图自动发现components        Map
 componentNamesAndLocations = findComponents(componentsConfig, getServletContext());         // 取得特别指定的components        Map
 specifiedComponents = componentsConfig.getComponents();         // 实际要初始化的comonents,为上述两种来源的并集        Set
 componentNames = createTreeSet();         componentNames.addAll(componentNamesAndLocations.keySet());        componentNames.addAll(specifiedComponents.keySet());         // 创建root controller        WebxRootController rootController = componentsConfig.getRootController();         if (rootController == null) {            rootController = (WebxRootController) BeanUtils.instantiateClass(componentsConfig.getRootControllerClass());        }         // 创建并将components对象置入resolvable dependencies,以便注入到需要的bean中        WebxComponentsImpl components = new WebxComponentsImpl(componentsContext,                componentsConfig.getDefaultComponent(), rootController, parentConfiguration);         beanFactory.registerResolvableDependency(WebxComponents.class, components);         // 初始化每个component        for (String componentName : componentNames) {            ComponentConfig componentConfig = specifiedComponents.get(componentName);             String componentPath = null;            WebxController controller = null;             if (componentConfig != null) {                componentPath = componentConfig.getPath();                controller = componentConfig.getController();            }             if (controller == null) {                controller = (WebxController) BeanUtils.instantiateClass(componentsConfig.getDefaultControllerClass());            }             WebxComponentImpl component = new WebxComponentImpl(components, componentName, componentPath,                    componentName.equals(componentsConfig.getDefaultComponent()), controller,                    getWebxConfigurationName());             components.addComponent(component);             prepareComponent(component, componentNamesAndLocations.get(componentName));        }         return components;    }     private void prepareComponent(WebxComponentImpl component, String componentLocation) {        String componentName = component.getName();        WebxComponentContext wcc = new WebxComponentContext(component);         wcc.setServletContext(getServletContext());        wcc.setNamespace(componentName);        wcc.addApplicationListener(new SourceFilteringListener(wcc, component));         if (componentLocation != null) {            wcc.setConfigLocation(componentLocation);        }         component.setApplicationContext(wcc);         // 将context保存在servletContext中        String attrName = getComponentContextAttributeName(componentName);        getServletContext().setAttribute(attrName, wcc);         log.debug("Published WebApplicationContext of component {} as ServletContext attribute with name [{}]",                componentName, attrName);    }

RequestContextBeanFactoryPostProcessor

【RequestContextBeanFactoryPostProcessor】public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {        // 先注册request/response/session,再从beanFactory中取得requestContexts。         // 创建全局的request实例。        register(beanFactory, ServletRequest.class,                createProxy(HttpServletRequest.class, beanFactory.getBeanClassLoader(), new RequestObjectFactory()));         // 创建全局的session实例。        register(beanFactory, HttpSession.class,                createProxy(HttpSession.class, beanFactory.getBeanClassLoader(), new SessionObjectFactory()));         // 创建全局的response实例。        register(beanFactory, ServletResponse.class,                createProxy(HttpServletResponse.class, beanFactory.getBeanClassLoader(), new ResponseObjectFactory()));         // 取得requestContexts时会激活requestContexts的初始化。        // 由于request/response/session已经被注册,因此已经可被注入到requestContexts的子对象中。        RequestContextChainingService requestContexts = (RequestContextChainingService) beanFactory.getBean(                requestContextsName, RequestContextChainingService.class);         // 创建全局的request context实例。        for (RequestContextInfo
 info : requestContexts.getRequestContextInfos()) {            Class
 requestContextInterface = info.getRequestContextInterface();            Class
 requestContextProxyInterface = info.getRequestContextProxyInterface();             register(                    beanFactory,                    requestContextInterface,                    createProxy(requestContextProxyInterface, beanFactory.getBeanClassLoader(),                            new RequestContextObjectFactory(requestContextProxyInterface)));        }    }
【RequestContextBeanFactoryPostProcessor&RequestObjectFactory】private static class RequestObjectFactory implements ObjectFactory {        public Object getObject() {            RequestAttributes requestAttrs = RequestContextHolder.currentRequestAttributes();             if (!(requestAttrs instanceof ServletRequestAttributes)) {                throw new IllegalStateException("Current request is not a servlet request");            }             HttpServletRequest request = ((ServletRequestAttributes) requestAttrs).getRequest();             if (request == null) {                throw new IllegalStateException("Current request is not a servlet request");            }             return request;        }    }
【RequestContextHolder】public abstract class RequestContextHolder  {     private static final boolean jsfPresent =            ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader());     private static final ThreadLocal requestAttributesHolder = new NamedThreadLocal("Request attributes");     private static final ThreadLocal inheritableRequestAttributesHolder =            new NamedInheritableThreadLocal("Request context"); public static RequestAttributes getRequestAttributes() {        RequestAttributes attributes = (RequestAttributes) requestAttributesHolder.get();        if (attributes == null) {            attributes = (RequestAttributes) inheritableRequestAttributesHolder.get();        }        return attributes;    } public static RequestAttributes currentRequestAttributes() throws IllegalStateException {        RequestAttributes attributes = getRequestAttributes();        if (attributes == null) {            if (jsfPresent) {                attributes = FacesRequestAttributesFactory.getFacesRequestAttributes();            }            if (attributes == null) {                throw new IllegalStateException("No thread-bound request found: " +                        "Are you referring to request attributes outside of an actual web request, " +                        "or processing a request outside of the originally receiving thread? " +                        "If you are actually operating within a web request and still receive this message, " +                        "your code is probably running outside of DispatcherServlet/DispatcherPortlet: " +                        "In this case, use RequestContextListener or RequestContextFilter to expose the current request.");            }        }        return attributes;    }

BeanFactoryPostProcessor终于结束了,看下finishRefresh,这也是个拓展点,主要是用来初始化controller和componentContext

【WebxComponentsContext】protected void finishRefresh() {        super.finishRefresh();        getLoader().finishRefresh();    }
【WebxComponentsLoader】public void finishRefresh() {        components.getWebxRootController().onFinishedProcessContext();         for (WebxComponent component : components) {            logInBothServletAndLoggingSystem("Initializing Spring sub WebApplicationContext: " + component.getName());             WebxComponentContext wcc = (WebxComponentContext) component.getApplicationContext();            WebxController controller = component.getWebxController();             wcc.refresh();        //留了拓展点,啥也没做            controller.onFinishedProcessContext();        }         logInBothServletAndLoggingSystem("WebxComponents: initialization completed");    }

容器初始化至此结束了,最后介绍下filter的初始化

转载于:https://my.oschina.net/tryUcatchUfinallyU/blog/288049

你可能感兴趣的文章
hibernate笔记01
查看>>
UNIX环境高级编程——进程管理和通信(总结)
查看>>
Ubuntu Git安装与使用
查看>>
接口测试理论基础
查看>>
C#操作实例总结(一)—— 系统操作
查看>>
python 正则表达式与re模块
查看>>
OFART: OpenFlow-Switch Adaptive Random Testing
查看>>
步步为营 SharePoint 开发学习笔记系列总结(转)
查看>>
表的查询
查看>>
【面试题】
查看>>
IPv6地址的ping、telnet等操作
查看>>
CDH- 测试mr
查看>>
SpringMVC配置及使用
查看>>
css中的层叠性及权重的比较
查看>>
LeetCode--026--删除排序数组中的重复项
查看>>
怎样在UICollectionView中添加Header和footer
查看>>
使用极光推送(www.jpush.cn)向安卓手机推送消息【服务端向客户端主送推送】C#语言...
查看>>
FZU 2107 Hua Rong Dao DFS
查看>>
加密与入侵检查
查看>>
淡入淡出js代码
查看>>