Sunday, August 16, 2009

perf4j vs. simon

1. perf4j的资料和例子要比simon详细一些。
2. perf4j和spring的集成要比simon好一些,simon现在还不能实现代理有参数构造函数的bean,此时simon会出现(Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given)异常(http://netfork.javaeye.com/blog/286215)。因此目前要想使用必须要么使用JDK自带的自动代 理,要么必须提供默认构造函数,要么修改spring的类。
3. perf4j和simon都提供了Annotation注解支持,但都依赖spring aop的实现,就是会有#2中的问题。
4. perf4j目前支持将日志信息写入日志文件,然后用命令行来查看结果。但是simon目前没有提供默认实现。但是可以通过callback来自己实现。
5. perf4j支持设置统计结果的显示步长,simon不能设置,但是simon提供了clear方法,可以清空当前内存中的统计信息重新开始统计,这一点perf4j默认实现不了,必须自己编程实现。
6. 目前项目中使用的是让perf4j来解析整个日志文件类来产生最后的结果,这样如果日志文件太大,统计分析会比较慢。

Spring AOP - Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given

今天在集成perf4j和javasimon到代码里的时候发现一些问题,就是本来在自己的测试代码里运行好好的东西,在放到项目代码里的时候总是报以下错误:
...
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
...
比 较了代码半天发现在自己的测试代码里没有用到有构造参数的spring bean,而在项目代码中很多的类都是通过有参数构造函数来创建的。而spring在借助cglib创建目标对象子类时,并没有对有参数构造函数做处理, 而是使用的默认我参数构造函数,这就导致了以上异常的出现。这里有一个很详细的文章对这个问题做了描 述,http://netfork.javaeye.com/blog/286215

Friday, August 7, 2009

Struts2中Action的@BeforeResult方法被执行两次问题


这个问题通常会在两种情况下发生
第一种是在标注了@BeforeResult的方法中有异常发生,这个时候struts2会调用这个方法多次,这个问题同事有很多人碰到过,解决办法是在标注了@BeforeResult的方法中捕获所有异常,然后添加到ActionError中。
第二种是出现的情况是在两个有继承关系的Action中都标注有@BeforeResult方法,这个时候struts就好调用子类中的
标注有@BeforeResult的方法两次,这个问题可以从xwork的源代码com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor中发现问题所在。
public void beforeResult(ActionInvocation invocation, String resultCode) {
Object action = invocation.getAction();
List methods = AnnotationUtils.findAnnotatedMethods(action.getClass(), BeforeResult.class);

if (methods != null && methods.size() > 0) {
Collections.sort(methods, new Comparator() {
public int compare(Method method1, Method method2) {
return method2.getAnnotation(BeforeResult.class).priority()
- method1.getAnnotation(BeforeResult.class).priority();
}
});
for (Method m : methods) {
try {
m.invoke(action, (Object[]) null);
} catch (Exception e) {
throw new XWorkException(e);
}
}
}
}

实现中首先是找到所有的标注有@BeforeResult的方法,然后在子类的实现上依次调用找到的方法,所以就出现了调用两次的问题。解决办法比较简单就是避免这种结构出现在自己的类中,或者自己写一些代码检查是不是已经执行过@BeforeResult中的方法。