webx在启动时通过:
com.alibaba.citrus.webx.servlet.WebxFrameworkFilter.init()==>ServletContext. getAttribute(attrName)
获取WebxComponentsContext。
后续调用过程:
WebxRootControllerImpl. handleRequest()
getComponents().findMatchedComponent(path).getWebxController().service(requestContext)
在service中:
PipelineInvocationHandle. Invoke()==>valve.invoke(this)
valve就是在pipeline中配置的阀门。
由于我们需要在screen层加一层aop:
<aop:config> <aop:aspect ref="requestParamCheck"> <aop:pointcut id="screenPointcut" expression="execution(public * com.x.z.*.module.screen.*.*(..))" /> <aop:before method="check" pointcut-ref="screenPointcut" /> </aop:aspect> </aop:config>
这时,如果screen实现的有接口,则screen所对应的bean应该是通过jdk动态代理创建的。例如:LoginScreen implements ILogin
//空接口 public interface ILogin { }
那边LoginScreen的bean实例:org.springframework.aop.framework.JdkDynamicAopProxy@a634f0e
这时就会出现异常:
Failed to process request /loginScreen/abc.htm, the r oot cause was UnadaptableModuleException: Could not adapt object to module: type=screen, name=LoginS creen, class=class com.sun.proxy.$Proxy8
抛出异常的代码:
// 从factory中装载
Object moduleObject = null;
Module module = null;
for (ModuleFactory factory : factories) {
moduleObject = factory.getModule(moduleType, moduleName);
if (moduleObject != null) {
break;
}
}
//此时 moduleObject 被赋值为LoginScreen的jdk动态代理实例org.springframework.aop.framework.JdkDynamicAopProxy@a634f0e
// 通过适配器转换接口
if (moduleObject != null) {
if (moduleObject instanceof Module) {
module = (Module) moduleObject; // 假如moduleObject直接实现了接口
} else {
for (ModuleAdapterFactory adapter : adapters) {
module = adapter.adapt(moduleType, moduleName, moduleObject);
if (module != null) {
break;
}
}
}
}
if (module == null) {
if (moduleObject != null) {
throw new UnadaptableModuleException("Could not adapt object to module: type=" + moduleType + ", name="
+ moduleName + ", class=" + moduleObject.getClass());
}
}
应该是 adapter.adapt(moduleType, moduleName, moduleObject)出现了问题
public Module adapt(String type, String name, Object moduleObject) {
if (!isAdaptableType(type)) {
return null;
}
Class<?> moduleClass = moduleObject.getClass();
Map<String, Method> handlers = getEventHandlers(moduleClass);
if (handlers == null) {//debug发现,是这里返回了null
return null;
}
ModuleInfo moduleInfo = new ModuleInfo(type, name);
FastClass fc = FastClass.create(moduleClass);
Map<String, MethodInvoker> fastHandlers = createHashMap(handlers.size());
for (Map.Entry<String, Method> entry : handlers.entrySet()) {
FastMethod fm = fc.getMethod(entry.getValue());
fastHandlers.put(entry.getKey(), getMethodInvoker(fm, moduleInfo, isEventHandlerSkippable()));
}
FastMethod preHandler = getFastMethod(fc, PRE_HANDLER);
FastMethod postHanlder = getFastMethod(fc, POST_HANDLER);
AbstractModuleEventAdapter adapter = createAdapter(moduleObject,
fastHandlers,
getMethodInvoker(preHandler, moduleInfo, false),
getMethodInvoker(postHanlder, moduleInfo, false));
try {
// 注入并初始化adapter(不是注入moduleObject,后者取决于factory的设置)
autowireAndInitialize(adapter, context, AbstractBeanDefinition.AUTOWIRE_AUTODETECT, type + "." + name);
} catch (Exception e) {
throw new ModuleLoaderException("Failed to configure module adapter", e);
}
return adapter;
}
if (handlers == null) {//debug发现,是这里返回了null
return null;
}
再看看getEventHandlers():
/** 取得事件处理方法。 */
private Map<String, Method> getEventHandlers(Class<?> moduleClass) {
Map<String, Method> handlers = null;
for (Method method : moduleClass.getMethods()) {
if (checkMethod(method)) {
String methodName = method.getName();
// doXyz()
if (methodName.length() > 2 && methodName.startsWith("do")//对以do开头的方法做map,以处理请求
&& Character.isUpperCase(methodName.charAt(2))) {
String eventName = toCamelCase(methodName.substring(2));
// default handler: doPerform()
if (DEFAULT_EVENT.equals(eventName)) {
eventName = null;
}
if (handlers == null) {
handlers = createHashMap();
}
handlers.put(eventName, method);
}
}
}
return handlers;
}
由于jdk动态代理产生的实例包含的方法来源于其所实现的接口,而ILogin接口中没有任何方法,更不会有以do开头的方法,所以getEventHandlers()返回null,导致异常。。
解决方案:
如果不想对screen中的所有do*()都定义接口,那么可以采用cglib做代理,只需要保证screen没有实现任何接口,spring就会自动使用cglib做代理,cglib是通过创造子类来实现代理的,所以代理子类肯定有do*()方法,getEventHandlers()就会返回do开头的方法map,就能够正常处理请求。
相关推荐
webx框架(淘宝框架),webx+spring+ibatis
WEBX是阿里巴巴的内部框架,“就是把页面与Service层之间的一些Servlet等公共的东西抽象出来,提供相应的服务以提高开发效率(《接口测试之Webx简介》—何晓峰 )”,可以看出,webx和传统的servlet-action模式的...
• 2004年11月,Webx 2.0和Spring框架整合。 • 从那以后,Webx 2.0一直在进化,但没有作根本性的改动。 • 2010年,Webx 3.0发布。Webx 3.0抛弃了Webx 2.0中过时的、从Turbine中发展而来的 Service框架,直接采用...
基于Webx Spring iBATIS的数据资产管理平台的设计与实现,沈慧,魏洪涛,根据数据资产的特征,结合在电子商务中分析数据的功能需求,设计并实现了基于Webx Spring iBATIS技术框架的数据资产管理平台。该平台主
阿里开源框架webx的文档,想要学习webx或者维护webx的开发者可以下载
webx3.0学习小结
webx3 启动顺序,webx使用总结,webx表单提交(感觉你还是看webx文档 貌似更加好哦!那个表单提交写的很是详细)
NULL 博文链接:https://itjiehun.iteye.com/blog/1299965
Webx及框架简介 ppt 格式
WEBX框架详解,更好的了解Taobao的开发过程,对于新手更容易上手。
Webx是一个基于 Spring的组件框架。组件是一个软件包,它可以被其它组件扩展,也可以扩展其它组件。利用这些特性,Webx不仅能够用来开发高度可定制的Web应用(这是它的主要功能),也能够用来帮助你开发高度可扩展...
NULL 博文链接:https://xj84.iteye.com/blog/1850955
该文档为官方webx框架文档,对webx进行了全面的讲解,非常实用。
1.webx是阿里巴巴开发的mvc框架(就是spring mvc又封了一层) 2.此项目是个完整的项目,修改数据库配置后可直接运行(搜索data-source.xml) 3.webx自带的持久层是ibatis,我改成了hibernate 3.此为maven项目,jar包在项目...
阿里巴巴内部J2EE平台 Webx框架简介,现在是webx3.0,而且已经开源!
淘宝开源Web开发框架Webx3.0介绍,内附宠物店程序作为例子详细解说webx框架的方方面面。
快速使用 webx 开发web 应用 Webx框架指南 Michael Zhou
webx框架是淘宝开发的比较流行的框架,这个是webx框架的入门介绍
WebX入门指南示例程序,通过结合博文:http://blog.csdn.net/fiboliu/article/details/50040273和代码讲解了,WebX入门级的使用指南!
• 扩展性 —— Webx 3.0对Spring做了扩展,使Spring Bean不再是“bean”,而是升级成“组件”。一个组件可以扩展另一个组件,也可以被其它组件扩展。这种机制造就了Webx的非常好的扩展性,且比未经扩展的Spring更易...