调试petstore-web在debug configurations面板的source tab页中添加项目所依赖的源代码包spring-web-3.2.7.RELEASE-sources.jar&spring-context-3.2.10.RELEASE-sources.jar&citrus-webx-all-3.2.2-sources.jar
初始配置:
引入webx3需要在web.xml文件中,引入以下监听
日志系统初始化
<listener><listener-class>com.alibaba.citrus.logconfig.LogConfiguratorListener</listener-class></listener>
Webx3框架初始化装载/WEB-INF/webx.xml, /WEB-INF/webx-*.xml
<listener><listener-class>com.alibaba.citrus.webx.context.WebxContextLoaderListener</listener-class></listener>
请求日志上下文设置
<filter-class>com.alibaba.citrus.webx.servlet.SetLoggingContextFilter</filter-class></filter>
请求拦截
<filter-class>com.alibaba.citrus.webx.servlet.WebxFrameworkFilter</filter-class></filter>
入口WebxContextLoaderListener:
WebxContextLoaderListener继承自spring的ContextLoaderListener。启动的入口方法为父类的createContextLoader,该方法是创建并初始化contextLoader对象使之成为整个应用的上下文装载器,WebxContextLoaderListener并没有复写父类的这个方法,而是复写了createContextLoader方法,设置WebxComponentsLoader为contextLoader。
WebxComponentsLoader:
WebxComponentsLoader继承自ContextLoader。覆盖了其中的几个方法,如:initWebApplicationContext,determineContextClass,customizeContext,toString方法。其中比较重要的是determineContextClass和customizeContext。
determineContextClass
determineContextClass这个方法是定义WebApplicationContext的实现类为WebxComponentsContext。父类ContextLoader默认的处理是从所在目录下的ContextLoader.properties中读取如下配置信息。WebxComponentsLoader通过WebxComponentsContext这个类来处理配置文件。
customizeContext
customizeContext方法主要就是设置WebxComponentsContext的loader为WebxComponentsLoader,这样在执行finishRefresh方法的时候会调用WebxComponentsContext的finishRefresh方法,然后该方法会去调用loader的postProcessBeanFactory方法。
WebxComponentsLoader的postProcessBeanFactory方法是在创建beanFactory之初被调用的,它往beanFactory中创建一个bean,对应的class为WebxComponentsCreator,这个类继承自BeanFactoryPostProcessor,而且它的order设置的顺序最末,所以会在PropertyPlaceholderConfigurer执行之后执行。
createWebApplicationContext
ContextLoader的createWebApplicationContext方法里, determineContextClass就是调用WebxComponentsLoader中对应的方法,把ApplicationContext设置为WebxComponentsContext。
WebxComponentsContext:
WebxComponentsContext的refresh方法是定义在org.springframework.context.support.AbstractApplicationContext.refresh()中的,代码如下
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; } } } |
(1)obtainFreshBeanFactory方法。其中的refreshBeanFactory方法代码如下, createBeanFactory方法在Webx3的XmlWebApplicationContext中覆盖过,创建了一个InheritableListableBeanFactory类型的对象,作为bean factory,这是WEBX3对spring进行扩展的一个bean factory。
protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } }catch (IOException ex) { throw new ApplicationContextException("I/O error parsing XML document for application context [" + getDisplayName() + "]", ex); } } |
InheritableListableBeanFactory从这个类的注释可以看出它的的两点重要功能:
1) 子context可继承parent,并能共享父context中的配置和资源;
2) 子context不能覆盖父context中已有的resolvableDependencies对象。否则, WebApplicationContext会自动注册非singleton的request对象 ,使得子context不能取得父context中注册的singleton proxy。通过这个类的处理,可以将request这类的对象注入到Module之中,实际上注入到Module中的是一个代理,对象的实际内容是在运行期从当前线程之中取得实际对象并填充的。
customizeBeanFactory完成annotation注册。通过对allowBeanDefinitionOverriding,allowCircularReferences属性的设置,控制bean fanctory中的bean能否被重写和循环引用。
loadBeanDefinitions方法用于装载应用中的beans。方法中定义XmlBeanDefinitionReader并设置如何去解析xml文档,然后先调用initBeanDefinitionReader方法,其中会调用 springext的XmlWebApplicationContext类, 通过initBeanDefinitionReader这个方法,处理相应的配置扩展点。最后调用loadBeanDefinitions解析xml文档,通过读取/WEB-INF/webx-*.xml和/WEB-INF/webx.xml,获知要装载的bean,然后在AbstractBeanDefinitionParser的parse方法中会调用registerBeanDefinition将bean信息注册到BeanFactory的beanDefinitionMap中去,但并没有完成初始化的操作,初始化这一步在后续进行。
(2)postProcessBeanFactory方法是初始化过程中很重要的一个步骤。该方法最终会调用WebxComponentsLoader的postProcessBeanFactory方法,手工注册WebxComponentsCreator类到BeanFactory中,用以保证初始化的顺序。在webx3中,因为components的初始化依赖于WebxConfiguration,而WebxConfiguration实例的创建使用了PropertyPlaceholderConfigure,因此这些对象要按照一定的顺序创建。首先初始化PropertyPlaceholderConfigure,然后WebxComponentsCreator,最后是其他的BeanFactoryPostProcessors。
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { 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); } |
(3)invokeBeanFactoryPostProcessors方法分为3步执行。
第一步是执行实现了BeanFactoryPostProcessor接口的类,这些类都是通过addBeanFactoryPostProcessor方法添加到ApplicationContext中去的(PropertyPlaceholderConfigurer);
第二步是按照优先级去执行实现了BeanFactoryPostProcessor以及PriorityOrdered接口的bean(WebxComponentsCreator);
第三步是按照优先级去执行实现了BeanFactoryPostProcessor以及Ordered接口的bean(RequestContextBeanFactoryPostProcessor);
最后是执行仅实现了BeanFactoryPostProcessor接口的bean。
(4)registerBeanPostProcessors方法。注册实现了BeanPostProcessor接口的类,顺序和BeanFactoryPostProcessor类似。
(5)finishBeanFactoryInitialization方法。通过getBean方法去实现bean的初始化。
(6)finishRefresh基于前面创建出来的components创建出其他的子component。
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"); } |
启动完成。
类图如下: