webx 容器初始化

来源:互联网 发布:淘宝上比较好的女鞋店 编辑:程序博客网 时间:2024/06/06 09:08
webx扩展了spring的容器加载机制,首先在结构上扩展了component层,构造出不同应用模块bean之间的隔离机制。

1.解析web.xml

和spring web程序一样,容器的加载是通过在web.xml中配置的listener实现的。servlet容器在实例化servlet context的时候会触发contextInitialized方法从而开启实例化容器的流程。

根据servlet规范,listener按照观察者模式设计,一旦监听到某个事件就执行某个方法。而web.xml文件中有WebxContextLoaderListener继承了ServletContextListener接口,就会调用contextInitialized方法。


2.分析WebxContextLoaderListener
该类的功能:监听ServletContext事件,加载Spring容器;
类的继承结构:

WebxContextLoaderListener中创建contextLoader

@Overrideprotected final ContextLoader createContextLoader() {    return new WebxComponentsLoader() {        @Override        protected Class<? extends WebxComponentsContext> getDefaultContextClass() {            Class<? extends WebxComponentsContext> defaultContextClass = WebxContextLoaderListener.this                    .getDefaultContextClass();            if (defaultContextClass == null) {                defaultContextClass = super.getDefaultContextClass();            }            return defaultContextClass;        }    };}


ContextLoaderListener中调用上面创建的contextLoader进行初始化webx容器

public void contextInitialized(ServletContextEvent event) {   this.contextLoader = createContextLoader();   if (this.contextLoader == null) {      this.contextLoader = this;   }   this.contextLoader.initWebApplicationContext(event.getServletContext());}


3.应用上下文结构


相对于Spring上下文中以bean为单位进行加载,webx新增加了组件的结构。在容器加载的时候webx默认会扫描web-info目录下的webx.xml 文件和webx-*xml文件,进行资源加载,创建容器。

webx将一个web应用分解成多个小应用模块:app1,app2等。将一个大的应用变成若干个小应用模块,并且配置文件相互隔离。
- 所有小应用模块共享一个Spring Root Context( 根容器 ),对应 webx.xml ,根容器的bean可以被注入到子容器中;反过来不行。
- 每个小应用独享一个Spring Sub Context( 子容器 ),对应 webx-*.xml ,子容器之间相互隔离,不可相互注入bean。
需要注意的是,即使web应用很简单,也至少配置一个子容器。

如何实现刚才所说的组件容器加载的呢?WebxComponentsContext继承了AbstractApplicationContext并对 postProcessBeanFactory 方法和 finishRefresh方法进行了覆写,也正是这两个方法实现了webx独特的component。这一点非常重要!

在配置文件中,例如webx-*.xml中导入其他的xml加载bean的时候,从根上下文中是加载不到这些bean的,要通过获取该模块的component对应的上下文才能获取。
WebApplicationContext context = WebApplicationContextUtils .getWebApplicationContext(getServletContext());WebxComponentsContext webxComponentsContext = (WebxComponentsContext)context;WebxComponents components = webxComponentsContext.getWebxComponents();WebxComponent component =  components.getComponent("home"); playService = (PlayService) component.getApplicationContext().getBean("playServiceImpl");


扩展加载component的结构图:


1)覆写postProcessBeanFactory方法,实际上是实例化WebxComponentsCreator内部类,用于初始化root component和sub component,并且将所有的sub component的父容器设置成root component,形成级联结构。

/** 初始化components。 */private WebxComponentsImpl createComponents(WebxConfiguration parentConfiguration,                                            ConfigurableListableBeanFactory beanFactory) {    ComponentsConfig componentsConfig = getComponentsConfig(parentConfiguration);    // 假如isAutoDiscoverComponents==true,试图自动发现components    Map<String, String> componentNamesAndLocations = findComponents(componentsConfig, getServletContext());    // 取得特别指定的components    Map<String, ComponentConfig> specifiedComponents = componentsConfig.getComponents();    // 实际要初始化的comonents,为上述两种来源的并集    Set<String> 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;}


2)- 覆写finishRefresh方法,遍历地所有的sub component,通过wcc.refresh方法初始化每个sub component中的bean。

/** 初始化所有components。 */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");}






0 0