google-code-export / nutz

Automatically exported from code.google.com/p/nutz
Apache License 2.0
1 stars 1 forks source link

事务拦截器报错 #194

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
代码:
配置文件:
{
    transactionLevel2 : {
        type : "org.nutz.aop.interceptor.TransactionInterceptor"
    },
    transactionIoc : {
        type : "features.Transaction"
    }
}
类:
public class Transaction {
    @Aop(value = {"transactionLevel2"})
    public void testTransaction() {
    }
}
public static void main(String[] args) {
    Ioc ioc = new NutIoc(new JsonLoader("ioc"));
    Transaction tran = ioc.get(Transaction.class, "transactionIoc");
    try {
        tran.testTransaction();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
异常堆栈太多了,提交不了,贴开始一部分上来,后面都是重复��
�:
java.lang.RuntimeException: java.lang.StackOverflowError
    at org.nutz.lang.Lang.wrapThrow(Lang.java:116)
    at org.nutz.lang.Lang.wrapThrow(Lang.java:115)
    at
org.nutz.aop.interceptor.TransactionInterceptor$1.run(TransactionInterceptor.jav
a:48)
    at org.nutz.trans.Trans.exec(Trans.java:122)
    at
org.nutz.aop.interceptor.TransactionInterceptor.afterInvoke(TransactionIntercept
or.java:42)
    at features.Transaction$$NUTZAOP._Nut_after(Unknown Source)
    at features.Transaction$$NUTZAOP.testTransaction(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
a:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at
org.nutz.aop.interceptor.TransactionInterceptor$1.run(TransactionInterceptor.jav
a:45)
    at org.nutz.trans.Trans.exec(Trans.java:122)
    at
org.nutz.aop.interceptor.TransactionInterceptor.afterInvoke(TransactionIntercept
or.java:42)
    at features.Transaction$$NUTZAOP._Nut_after(Unknown Source)
    at features.Transaction$$NUTZAOP.testTransaction(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
a:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at
org.nutz.aop.interceptor.TransactionInterceptor$1.run(TransactionInterceptor.jav
a:45)
    at org.nutz.trans.Trans.exec(Trans.java:122)

Original issue reported on code.google.com by happyday...@gmail.com on 19 May 2010 at 9:07

GoogleCodeExporter commented 9 years ago
这是要拦截的方法
    @Aop(value = {"transactionLevel2"})
    public void testTransaction() {
        User user = dao.fetch(User.class, 1);
        Date oldDate = user.getInDate();
        Date newDate = (Date) oldDate.clone();
        oldDate.setDate(R.random(1, 100));
        newDate.setDate(50);
        user.setInDate(oldDate);
        dao.update(user);
        System.out.println("oldDate = " + oldDate);
        System.out.println("newDate = " + newDate);
        if (oldDate.before(newDate)) {
            System.out.println("正常");
        } else {
            System.out.println("异常");
            throw new RuntimeException();
        }
    }

Original comment by zozoh...@gmail.com on 19 May 2010 at 9:13

GoogleCodeExporter commented 9 years ago
然后在这里调用
    public void testTransaction() {
        Transaction tran = ioc.get(Transaction.class, "transactionIoc");
        tran.testTransaction();
    }

System.out.println("oldDate = " + oldDate);
System.out.println("newDate = " + newDate);

输出两个日期
oldDate = 2013-06-01
newDate = 2013-06-19

Original comment by zozoh...@gmail.com on 19 May 2010 at 9:15

GoogleCodeExporter commented 9 years ago
执行后,出现什么异常?
会打印出“正常”吗?
数据库里的记录会变成 2013-06-19 吗?

   不会
   正常都打印不出来
   java.lang.RuntimeException: java.lang.StackOverflowError
   报这样的错误

java.sql.Date 是吧

  是的

如果你把  public void testTransaction() 都删掉,就留一句 
System.out.println("正常");
看看会不会输出呢?

   也不会输出
   应该是拦截器内部的问题吧

Original comment by zozoh...@gmail.com on 19 May 2010 at 9:17

GoogleCodeExporter commented 9 years ago

Original comment by zozoh...@gmail.com on 19 May 2010 at 9:18

GoogleCodeExporter commented 9 years ago
认真想了想,的确非常有问题

returnValue[0] = method.invoke(obj, args);

这一句,就会导致堆栈溢出, 因为就是调用原本的方法.

杯具了.

Original comment by wendal1985@gmail.com on 19 May 2010 at 9:24

GoogleCodeExporter commented 9 years ago

Original comment by wendal1985@gmail.com on 19 May 2010 at 9:24

GoogleCodeExporter commented 9 years ago
恩, 看来只能等我把Aop重新实现才行了. 
现在的模型,无法处理这样的情况.
现有模型:

public T exe(Object..args){
 try{
     if 全部拦截器的beforeInvoke返回true
        执行原有方法
     陆续执行 全部拦截器的afterInvoke方法
     返回结果
 } catch (一般异常){
      陆续执行 全部拦截器的whenExp()方法,如果返回true,则抛出异常
 }
 catch (Error)
{
陆续执行 
全部拦截器的whenError()方法,如果返回true,则抛出异常
}
返回默认结果 0/false/null
}

故,我最近偷偷地在写另外一种模型, 类似于Filter

Original comment by wendal1985@gmail.com on 19 May 2010 at 9:35

GoogleCodeExporter commented 9 years ago
我正在实现的一种模型:

1. 一个AopCallable接口, 
任何被改造的类,都会实现这个接口.其中就一个方法, void
_aop_invoke(int index,Object[] args) 
用于调用原有方法,类似于CGlib的FastClass或FastMethod
2. 一个Chain实现类,持有被Aop的对象/方法/参数/返回值等.

我晚上提交一些代码上去吧.

原有的模型, 很轻便,但是无法包裹一个方法.

Original comment by wendal1985@gmail.com on 19 May 2010 at 9:39

GoogleCodeExporter commented 9 years ago

Original comment by wendal1985@gmail.com on 19 May 2010 at 9:40

GoogleCodeExporter commented 9 years ago
method.invoke(obj,args) 
...
原来即使是 super 的 method, invoke 一下原来的 obj 
,还是不会直接调到 super 啊。

杯具 ...

你能详细写一个新的模型的实现原理吗? 写成一个 
wiki,放在 manual/aop/ 里面,比如叫 aop_solution.man

Original comment by zozoh...@gmail.com on 19 May 2010 at 10:33

GoogleCodeExporter commented 9 years ago
好的.

提交一个新的实现: r1243 r1244

现在的事务拦截器应该已经可用了.

Original comment by wendal1985@gmail.com on 19 May 2010 at 4:08

GoogleCodeExporter commented 9 years ago
................ 这么快?

Original comment by zozoh...@gmail.com on 19 May 2010 at 5:41

GoogleCodeExporter commented 9 years ago
超人不是一天炼成的,哈哈

Original comment by wendal1985@gmail.com on 20 May 2010 at 12:07

GoogleCodeExporter commented 9 years ago
Fix in 1.a.28

Original comment by wendal1985@gmail.com on 23 May 2010 at 3:48