您的位置:首页 > 其它

webx3.0-容器初始化

2014-07-07 18:12 176 查看

概念介绍

Contexts

WebxComponentsContext

----类介绍:所有组件的共有上下文,即父容器,对应的默认spring配置文件为“webx.xml”
----成员变量
WebxComponentsLoader:因为beanFactory的行为均定义在WebxComponentsLoader中,故持有此变量
----成员函数
getWebxComponents:从加载器中取得webxComponents
postProcessBeanFactory:拓展点之一,使用该拓展点旨在合理的时间内创建components和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:

<?xml version="1.0" encoding="GBK"?>
<web-app version="2.4" xmlns="<a href="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd ">

<context-param>
<param-name>loggingRoot</param-name>
<param-value>/Users/apple/workspace/3.0/petstore/logs</param-value>
</context-param>
<context-param>
<param-name>loggingLevel</param-name>
<param-value>warn</param-value>
</context-param>
<context-param>
<param-name>loggingCharset</param-name>
<param-value>UTF-8</param-value>
</context-param>

<listener>
<listener-class>com.alibaba.citrus.logconfig.LogConfiguratorListener</listener-class>
</listener>

<!-- װ��/WEB-INF/webx.xml, /WEB-INF/webx-*.xml -->
<listener>
<listener-class>com.alibaba.citrus.webx.context.WebxContextLoaderListener</listener-class>
</listener>

<filter>
<filter-name>mdc</filter-name>
<filter-class>com.alibaba.citrus.webx.servlet.SetLoggingContextFilter</filter-class>
</filter>

<filter>
<filter-name>webx</filter-name>
<filter-class>com.alibaba.citrus.webx.servlet.WebxFrameworkFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>mdc</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>webx</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

</web-app>

在这里,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<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;
}

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<? extends RequestContext> requestContextInterface = info.getRequestContextInterface();
Class<? extends RequestContext> 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的初始化
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: