wex框架初始化完全解析.docx
- 文档编号:10479106
- 上传时间:2023-02-13
- 格式:DOCX
- 页数:21
- 大小:23.47KB
wex框架初始化完全解析.docx
《wex框架初始化完全解析.docx》由会员分享,可在线阅读,更多相关《wex框架初始化完全解析.docx(21页珍藏版)》请在冰豆网上搜索。
wex框架初始化完全解析
Webx框架初始化解析
前言:
对整个webx框架的初始化进行了全面的分析,webx是怎么一步一步的初始化的,组件与组件时间如何相互通信,web层怎么能够方便的拿到service的东西,service的资源存在什么地方;外部程序怎样拿到webxcontroller的实例;又怎样保证car与car之间的独立,car与car之间又是怎么共享资源的,configration在整个环境是怎么起到核心作用的;
希望这样的文章会对大家有所帮助;
主要是分析wex框架的内部初始化情况,和结构分析;
(1):
com.alibaba.webx.WebxControllerServlet为整个系统的门面,初始化工作也在这里进行;
web.xml里面:
michael已经说的很清楚webx主控制器;
--Webx主控制器。
-->
WebxControllerServlet继承com.alibaba.webx.controller.AbstractWebxControllerServlet;
AbstractWebxControllerServlet继承自HttpServlet;
容器启动的时候,因为WebxController的启动状态是
所以直接执行WebxControllerServlet
按照servlet的规范首先执行init();
WebxControllerServlet直接执行父类AbstractWebxControllerServlet的init();
publicvoidinit()throwsServletException{
try{
configure();
log.info("WebxController:
init()ReadytoRumble!
");
}catch(Exceptione){
log.error("WebxController:
init()failed",e);
//这个异常将被servletengine记录到servletlog中。
UnavailableExceptionue=newUnavailableException("WebxController:
init()failed:
"
+e.getMessage());
ue.initCause(e);
throwue;
}
}
以上又是一个比较经典的模板应用,init()方法里面执行configure()方法,但是AbstractWebxControllerServlet定义的configure十一个抽象方法:
protectedabstractvoidconfigure()throwsWebxInitializationException;
并且由子类实现,所以直接执行子类的configure();具体业务逻辑子类化;
WebxControllerServlet的configure()方法中主要进行两个操作,
一初始化WebxController,
二将相关的servletConfig对象放到ServletContext中;
WebxControllerServlet中属性
privateWebxControllercontroller;光看名字就知道十一个比较重要的对象;
所以时刻要注意它;
分析configure():
protectedvoidconfigure()throwsWebxInitializationException{
controller=WebxUtil.getWebxController(getServletContext());
if(controller==null){
WebxLoaderloader=newWebxLoader(log,getServletContext(),
getServletConfig());
loader.configure();
controller=loader;
}
//将servletConfig放在servletContext中,供rundatafilter使用。
getServletContext().setAttribute(WEBX_CONTROLLER_SERVLET_CONFIG_KEY,getServletConfig());
}
这里首先用WebxUtil工具类根据ServletContex对象来初始化controller;
调用WebxUtil的
publicstaticWebxControllergetWebxController(ServletContextcontext){};
请看具体方法:
publicstaticWebxControllergetWebxController(ServletContextcontext){
WebxControllercontroller=null;
try{
Referenceholder=(Reference)
context.getAttribute(WEBX_CONTROLLER_KEY);
//context里面并没有这个属性,
这里拿出来应该是空的;
controller=(WebxController)holder.get();
}catch(ClassCastExceptione){
}catch(NullPointerExceptione){
}
returncontroller;
}
这里返回的controller应该是空的,因为context里面没有注入“webx.controller”属性;
接下来应该执行:
WebxLoaderloader=newWebxLoader(log,getServletContext(),getServletConfig());
WebxLoader实现了com.alibaba.webx.controller.WebxController和
com.alibaba.webx.WebxConstant
com.alibaba.webx.controller.WebxController是webx框架的核心调度者,是mvc框架的入口,
它里面包含了获取大量资源的方法,
需要用的上下文对象都在接口里面提供了的;
例如可以通过接口拿到:
ServletContext,ServiceManager(service管理器),Scheme(scheme方案初始化配置的方案),
RunDataService(RunData服务),ThreadContextService(线程范围的singleton服务),WebxComponent等信息;
com.alibaba.webx.WebxConstant包含一些配置信息,关于webxfreamwork的常量定义;
现在我们应该看一下实现类是怎么的结构,以及它是怎样工作的;
com.alibaba.webx.WebxLoader
首先通过构造函数进行初始化,传入日志对象,servlet上下文对象,servletConfig对象;
WebxLoaderloader=newWebxLoader(log,getServletContext(),getServletConfig());
loader初始化成功之后,
执行loader.configure();这一步是初始化了webx的所有配置;
接下来可能要花大量的篇幅讲解很多初始化工作虽然有点枯燥;
(2)真正的controller是怎样产生的:
在这里要注意看注释的编号对应下面的具体解释;
WebxLoader的configure()
publicvoidconfigure()throwsWebxInitializationException{
/*****
(一)创建日志输出路径,看后面的注解*******/
FileloggingRoot=configureLoggingRoot();
/*****
(二)初始化WebappBootstrapResourceLoaderService*****
WebappBootstrapResourceLoaderServiceresourceLoader=newWebappBootstrapResourceLoaderService(servletContext);
//在配置文件中可以使用如下变量:
//${loggingRoot}
//${server.host}
//${server.addr}
//以及所有System.getProperties()中的变量
Propertiesprops=newProperties(System.getProperties());
/*******(三)为配置log4j,取出相关属性******/
props.setProperty(LOGGING_ROOT_KEY,loggingRoot.getAbsolutePath());
props.setProperty(LOCAL_HOST_KEY,SystemUtil.getHostInfo().getName());
props.setProperty(LOCAL_ADDRESS_KEY,SystemUtil.getHostInfo().getAddress());
/********(四)配置log4j日志系统。
***************/
configureLog4j(resourceLoader,props);
//现在,logging系统应该已经可以工作了。
log.info("===================================================");
log.info("Loggingrootis"+loggingRoot);
/********(五)取得scheme的实例**************/
scheme=configureScheme(resourceLoader);
/********(六)取得规格化的servletPaths********/
servletPaths=configureServletPaths();
/********(七)取得webx配置文件*************/
Configurationconfiguration=configureWebx(resourceLoader,props,scheme);
/********(八)设置默认的services和配置项******/
scheme.applyDefaultConfiguration(resourceLoader,configuration,props);
if(log.isDebugEnabled()){
log.debug("WebxControllerinitializedwithconfiguration:
\n"
+(ConfigurationUtil.list(configuration)));
}
/********(九)初始化servicemanager**********/
serviceManager=configureServiceManager(resourceLoader,configuration,scheme);
/********(十)其它有关WebxController配置******/
configureWebxController();
/********(十一)如果指定了initAllServices,则强制初始化所有services***********/
configureAllServices();
}
注解:
(一)创建日志输出路径的目录,这里有三种策率,第一种是默认策率,首先会取你的user.home,我的user.home是:
C:
\DocumentsandSettings\liangkuan,
然后用user.home+/.webx+ServletName+/logs,最终中生成的路径是C:
\DocumentsandSettings\liangkuan\.webx\WebxController\logs+log4j.xml中配置的路径变量。
以我本机为例;
但是构建目录的时候首先会去寻找servletConfig里面关于日志的配置参数,来决定路径,如果在servletConfig中没有找到的话,
会去servletContext里面找配置参数,如果两者都没有找到就会直接用第一种默认策率来作为日志输出路径,相当灵活;
以我的环境为例,因为我的servlet里面配置了
--这个参数是会在antx.property文件里面注入的-->
所以直接就会在servletConfig里面找;
实现用到的相关类和:
WebxLoader.configureLoggingRoot(),
.findInitParameter(),
mon.lang.SystemUtil的getHomeDir();
(二)初始化WebappBootstrapResourceLoaderService
简单讲下WebappBootstrapResourceLoaderService的结构
WebappBootstrapResourceLoaderService继承
com.alibaba.service.resource.BootstrapResourceLoaderService
BootstrapResourceLoaderService实现com.alibaba.service.resourceResourceLoaderService,com.alibaba.service.MultiInstance;(实现它可以有多个实例)
这个初始化操作只做了3个事情:
1:
执行父类的非缺省构造函数,进本上什么都没有做;
2:
setLoggerReady(false),设置日志并没有准备好;
3:
传入servletContext属性;
this.servletContext=servletContext;
这是一个功能强大的资源装载器;可以读取各种资源,例如url,file等;这里的资源装载器主要是针对web应用的资源装载器实例;
(三)将和log4j相关的属性装入资源文件;
LOGGING_ROOT_KEY对应的是日志输出的地址,LOCAL_HOST_KEY对应的是主机名,LOCAL_ADDRESS_KEY对应的是ip地址;
都是通过InetAddress取出地址相关属性的,对这个些类不熟悉可以去看一下网络编程;
在SystemUtil里面使用了几个静态内部类,并且构造函数都是私有的,主要是防止外面直接创建;
(四)配置log4j应用
configureLog4j(resourceLoader,props);
这里传入了资源装载器,和相关的资源文件;
首先要取出log4j配置文件的路径,这里还是三种策率:
(1)如果servletConfig里面有配置文件的引用路径优先考虑;
(2)如果servletConfig里面没有直接在servletContext里面寻找;
(3)如果servletContext里面也不能找到直接用缺省配置/WEB-INF/log4j.xml;
接下来把路径生成相关的url对象;然后把文件取出来;
这里对log4j的配置文件有两种解析方式,如果配置文件名为*.xml,则使用DOMConfigurator,否则使用PropertyConfigurator。
现在log4j可以工作了所以进行下面操作resourceLoader.setLoggerReady(true);
现在打日志就没有问题了;
(五)取得Scheme的实例
首先取得schemeName先在servletConfig里面找如果没有去servletContext里面找如果都没有找到暂时为turbine;
构造一个名为webx.scheme.turbine的serviceId,这里的serviceId是一个文件的名字;
这个文件里面存有一条信息com.alibaba.turbine.scheme.TurbineScheme,从这里应该看出来这是一个类的全名,并且可能是Scheme的实现类;
接下来ClassLoaderUtil来装载这个类,ClassLoaderUtil.loadServiceClass(serviceId)这个方法指定了当前线程的类装载器来装载这个类;
在这里构造了一个完整的路径名:
META-INF/services/webx/scheme/turbine,并且用当前的类装载器的getResource()方法把文件路径转换成url,
然后直接把输入流打开;得到一个完整类名,并且用当前类装载器把
com.alibaba.turbine.scheme.TurbineScheme装载;
个人觉得这样的实现有点麻烦;类装载之后实例化
com.alibaba.turbine.scheme.TurbineScheme;
关于TurbineSchemeMichael在注释中写到经典的webx方案,可见它的重要性,在后面使用到它的地方将为大家介绍;
(六)取得取得web.xml中定义的servletpaths,并规格化之,让我们拿出的请求路径更加有规律;
这里会在servletConfig,servletContext去找webx.servlet.paths如果找不到缺省为空字符串;根据我这里的上下文路径这里没有这个参数;
(七)Configuration配置对象的接口,
Configurationconfiguration=configureWebx(resourceLoader,props,scheme);
这里要去找一个webxConfiguration的配置路径,首先在servletConfig,servletContext去找初始化参数webx.configuration,
如果都没有找到的话使用缺省值webxConfiguration=/WEB-INF/webx.xml而在当前系统中用的是缺省配置;
用web资源装载器得到/WEB-INF/webx.xml对应的url;
从这个配置文件的名称应该可以看出这里拉出了webx初始化的开端;
接下来读取webx配置文件,将配置文件映射为Configuration对象,
接下来会在servletConfig,servletContext中去找参数webx.configuration.loader.class
如果找不到的话就以默认值com.alibaba.webx.configuration.WebxConfigurationLoader为使用类;
WebxConfigurationLoader调用了JellyDigester的parse();这里声明了一个内部类privateclassDefaultJellyContextextendsJellyContext{}
configuration最终是通过Jelly引擎解析出来的;Jelly是一种基于java的脚本引擎,提供了解析xml的功能,它还具有比较强的动态特性;
接下来在web.xml中取出ponents,这里是在servletContext中取到的,取出了六个组件auction,member,mytaobao,common,shop,message
并且为每一个组件也就是car包分配一个资源装载器的实例;实现代码如下:
ResourceLoaderServicecomponentResourceLoader=(ResourceLoaderService)resourceLoader
.getInstance(componentName);
根据配置将每一个组件的配置文件转换成Configuration,并且和主要的Configuration对象进行合并,具体实现代码如下:
car包下的Configuration合并到总的Configuration时,key全部变为car包的componentname+key值;
publicstaticvoidloadComponent(Configurationconfiguration,StringcomponentName,
StringclassName,URLurl,Mapproperties)throwsDigesterException{
ConfigurationcomponentConfiguration=load(className,url,properties);
//将componentName加入到services.instances中,确保不重复。
if(!
configuration.getList(ServiceManager.SERVICE_INSTANCES_KEY).
contains(componentName)){
configuration.addProperty(ServiceManager.SERVICE_INSTANCES_KEY,componentName);
}
//将component配置加入到主配置中。
ConfigurationUtil.merge(configuration,componentConfiguration,componentName);
}
}
(八):
调用com.alibaba.turbine.scheme.TurbineScheme的applyDefaultConfiguration()方法;
这一步主要是初始化webx的默认配置;将相关配置文件里面配置的信息加入到Configuration中;
1:
首先将webx-default.xml中的配置合并到总的configuration对象中,具体步骤如下:
用web资源装载器寻找/WEB-INF/webx-default.xml如果这个文件存在,生成对应于/WEB-INF/webx-default.xml的Configuration;
生成Configuration都是用的Jelly来解析xml生成的Configuration对象;
第一步将configuration对象里面标记为services的配置信息读取出来,根据configur
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- wex 框架 初始化 完全 解析