论坛首页 Java企业应用论坛

Annotation & Reflection 学习 及 问题

浏览 3543 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-11-26  

最近在学习Anntation和Reflection,一直希望能做一个实际的应用.

所以,假象了一个例子,比如说在方法前加上Annotation来表明方法是否要进行事务处理,然后通过动态代理来执行.

1 MyAnnotationI

java 代码
  1. public interface MyAnnotationI {   
  2.     public void printString();   
  3.   
  4.     public void printString1();   
  5. }   

java 代码
  1. public class MyAnnotationImpl implements MyAnnotationI {   
  2.     @MyAnnotation(isTransaction ="yes")   
  3.     public void printString() {   
  4.         System.out.print("\n"+" don some thing");   
  5.     }   
  6.        
  7.     @MyAnnotation(isTransaction="yes")   
  8.     public void printString1() {   
  9.         System.out.print("\n"+" good work");   
  10.     }   
  11.        
  12. }  

 

3 然后是定义的Annotation

java 代码
  1. @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)   
  2. public @interface MyAnnotation {   
  3.     String isTransaction();   
  4. }   

 

我希望能在执行 MyAnnotationImpl 的;两个方法是做一个判断,来看是否执行事务代码. 下面是我写的代理类

 

java 代码
  1. public class MyHandler implements InvocationHandler {   
  2.     private Object o;   
  3.   
  4.     public MyHandler(Object delegate) {   
  5.         o = delegate;   
  6.     }   
  7.   
  8.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
  9.         Object a = null;   
  10.         try{   
  11.         System.out.print("\n"+"Start transaction ");   
  12.         a = method.invoke(o, args);   
  13.         System.out.print("\n"+"end transaction ");   
  14.         }   
  15.         catch(Exception e)   
  16.         {   
  17.             System.out.print("\n"+"Exception");   
  18.         }   
  19.         return null;   
  20.     }   
  21.   
  22. }  

 

也就是希望在方法上有isTransaction ="yes"的方法前后执行两行代码.

下面是运行代码

 

java 代码
  1. public class MyAnnotationTest {   
  2.   
  3.     
  4.   
  5.     public  void dynamicProxy()   
  6.     {   
  7.            
  8.     }   
  9.     public static void main(String[] args) {   
  10.         try {   
  11.             Class bean = Class.forName("com.my.annotation.one.MyAnnotationImpl");   
  12.             Method method[] = bean.getMethods();   
  13.             for (int i = 0; i < method.length; i++) {   
  14.                 if (method[i].getName().equals("printString1")) {   
  15.                     MyAnnotation an = method[i].getAnnotation(MyAnnotation.class);   
  16.                     if(an.isTransaction().equals("yes"))   
  17.                     {   
  18.                       Object o =   bean.newInstance();   
  19.                         InvocationHandler handler = new MyHandler(bean.newInstance());   
  20.                         MyAnnotationI proxy = (MyAnnotationI) Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(),   
  21.                                 handler);   
  22.                         Method m =     proxy.getClass().getDeclaredMethod("printString1"null);   
  23.   
  24.                         m.invoke(proxy, new Object[]{});   
  25.                     }   
  26.                 }   
  27.   
  28.             }   
  29.   
  30.         } catch (Exception e) {   
  31.             System.out.println(e.toString());   
  32.         }    
  33.   
  34.     }   
  35.   
  36. }  

 

输出结果如下:

Start transaction
 good work
end transaction

 这样看似通过Annotation和Reflection 实现了一个事物,但是我有些问题.

1 这里是我指明了要调用哪个方法的,如果我也不知道具体执行那个方法.需要在运行时动态的去判定,我该怎么做?

2 我在 proxy.getClass().getDeclaredMethod("printString1"null)中调用的无参数的方法,如果我的执行方法有参数, 程序怎么知道有那些 参数,如果得到要调用的方法?

希望明白的朋友给我指点一二.

   发表时间:2007-11-27  
仔细来看LZ的两个问题其实都是因为代码没有写好的缘故造成的,其实LZ应该在InvocationHandler 的实现invoke方法中获取方法注解声明,然后判断是否需要进行事务处理,如果有声明则在invoke中将该方法的调用放入到事务中,否则则直接调用,不知道这样说LZ明白么?应该将事务处理逻辑放到invoke中。
0 请登录后投票
   发表时间:2007-11-27  
calmness 写道
仔细来看LZ的两个问题其实都是因为代码没有写好的缘故造成的,其实LZ应该在InvocationHandler 的实现invoke方法中获取方法注解声明,然后判断是否需要进行事务处理,如果有声明则在invoke中将该方法的调用放入到事务中,否则则直接调用,不知道这样说LZ明白么?应该将事务处理逻辑放到invoke中。


ok,非常感谢。我按照3楼的建议。做了些修改,把是否执行事务的判断放到invoke中执行,这样我说的问题解决了。
但是现在会抛出一个异常--java.lang.reflect.InvocationTargetException(对带有指定参数的指定对象调用由此 Method 对象表示的基础方法。实在不明白什么意思)

是在invoke执行后抛出的,望3楼在帮我解答一下。
对了忘了贴出代码
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object a = null;
        try {
            
            if (method.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation an = method.getAnnotation(MyAnnotation.class);
                if (an.isTransaction().equals("yes") && an != null) {
                    System.out.print("\n" + "Start transtion");
                    a = method.invoke(o, args);
                    System.out.print("\n" + "end transtion");
                } else {
                    a = method.invoke(o, args);
                }
            }
            return null;
        } catch (Exception e) {
            System.out.print("\n" + "invoke Exception");
        }
        return a;
    }
0 请登录后投票
   发表时间:2007-11-27  
这段代码应该是没问题的,最好能把测试的代码以及出错的详细信息都发上来。
0 请登录后投票
   发表时间:2007-11-28  
calmness 写道
这段代码应该是没问题的,最好能把测试的代码以及出错的详细信息都发上来。

这是我的测试代码
 Class bean = Class.forName("com.my.annotation.two.MyAnnotationImpl");
            // Method method[] = bean.getMethods();
            Object o = bean.newInstance();
            InvocationHandler handler = new MyHandler(bean.newInstance());
            MyAnnotationI proxy = (MyAnnotationI) Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), handler);
            Method method[] = proxy.getClass().getMethods();
            for (int i = 0; i < method.length; i++) {
                    Object oo = method[i].invoke(proxy, new Object[] {});
            }


如果我直接通过proxy调用具体的方法时,是没有问题的。
另外,我把annotation写到interface里面了。
然后出现哪个异常,不知道原因了。
0 请登录后投票
   发表时间:2007-11-28  
bxf12315 写道
calmness 写道
这段代码应该是没问题的,最好能把测试的代码以及出错的详细信息都发上来。

这是我的测试代码
 Class bean = Class.forName("com.my.annotation.two.MyAnnotationImpl");
            // Method method[] = bean.getMethods();
            Object o = bean.newInstance();
            InvocationHandler handler = new MyHandler(bean.newInstance());
            MyAnnotationI proxy = (MyAnnotationI) Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), handler);
            Method method[] = proxy.getClass().getMethods();
            for (int i = 0; i < method.length; i++) {
                    Object oo = method[i].invoke(proxy, new Object[] {});
            }


如果我直接通过proxy调用具体的方法时,是没有问题的。
另外,我把annotation写到interface里面了。
然后出现哪个异常,不知道原因了。


晕,看到这么长串测试代码我的头也晕了,你为什么要用invoke来测试?你直接用代理的类来call方法就可以了啊,
proxy.printString();
这样就行了。我就搞不懂你为什么还要绕个大圈最后用invoke来调用,郁闷。
0 请登录后投票
   发表时间:2007-11-29  
calmness 写道
bxf12315 写道
calmness 写道
这段代码应该是没问题的,最好能把测试的代码以及出错的详细信息都发上来。

这是我的测试代码
 Class bean = Class.forName("com.my.annotation.two.MyAnnotationImpl");
            // Method method[] = bean.getMethods();
            Object o = bean.newInstance();
            InvocationHandler handler = new MyHandler(bean.newInstance());
            MyAnnotationI proxy = (MyAnnotationI) Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), handler);
            Method method[] = proxy.getClass().getMethods();
            for (int i = 0; i < method.length; i++) {
                    Object oo = method[i].invoke(proxy, new Object[] {});
            }


如果我直接通过proxy调用具体的方法时,是没有问题的。
另外,我把annotation写到interface里面了。
然后出现哪个异常,不知道原因了。


晕,看到这么长串测试代码我的头也晕了,你为什么要用invoke来测试?你直接用代理的类来call方法就可以了啊,
proxy.printString();
这样就行了。我就搞不懂你为什么还要绕个大圈最后用invoke来调用,郁闷。


其实,后来我也发现我这样做意义不大了。我本意就是想把我的实现类里面的2个方法都执行一下,看看输出。出了这个异常就像看看怎么回事,呵呵。
其实,就像你说的那样完全可以call了。
目的主要是想搞清楚这个异常为什么出,我觉得可能我在对Annotation和Reflection了解上还存在问题。
多谢了
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics