职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 1456|回复: 10

注解+动态代理的一个例子

[复制链接]
芷馨 发表于 2011-8-29 10:48 | 显示全部楼层 |阅读模式
在公司没事干了,学习下动态代理模式(关于代理的基础只是有很多帖子都有我就不重复了),做了个注解动态代理的例子,给那些学习注解或动态代理的初学者。
花了将近1小时,没做个什么优化,大牛勿喷。
几个主要的类:
注解类:
  
package test2;   
  
import java.lang.annotation.ElementType;   
import java.lang.annotation.Retention;   
import java.lang.annotation.RetentionPolicy;   
import java.lang.annotation.Target;   
  
  
@Retention(RetentionPolicy.RUNTIME)   
@Target(ElementType.METHOD)   
public @interface ProxyTag {   
    public Class proxyClass();   
}  

package test2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ProxyTag {
        public Class proxyClass();
}
  
代理类父类:
  
import java.lang.reflect.InvocationHandler;   
import java.lang.reflect.Method;   
import java.lang.reflect.Proxy;   
  
public abstract class  ProxyBean implements InvocationHandler{   
      
    private Object o;   
  
      
    private String methodName;   
      
    public Object bind(Object obj,String methodName){   
        this.o = obj;   
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);   
    }   
      
      
    public Object invoke(Object proxy, Method method, Object[] obj)   
            throws Throwable {   
        if(method.getName().equals(methodName)){   
            this.before();   
            Object result = method.invoke(o, obj);   
            this.after();   
            return result;   
        }else{   
            Object result = method.invoke(o, obj);   
            return result;   
        }   
           
    }   
      
    public abstract void before();   
      
    public abstract void after();   
}  

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public abstract class  ProxyBean implements InvocationHandler{
       
        private Object o;

       
        private String methodName;
       
        public Object bind(Object obj,String methodName){
                this.o = obj;
                return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
        }
       
       
        public Object invoke(Object proxy, Method method, Object[] obj)
                        throws Throwable {
                if(method.getName().equals(methodName)){
                        this.before();
                        Object result = method.invoke(o, obj);
                        this.after();
                        return result;
                }else{
                        Object result = method.invoke(o, obj);
                        return result;
                }
               
        }
       
        public abstract void before();
       
        public abstract void after();
}代理工厂:
  
import java.lang.reflect.Constructor;   
import java.lang.reflect.InvocationTargetException;   
import java.lang.reflect.Method;   
  
public class ProxyFactory {   
      
      
    public static <T> T getProxyBean(Class<T> clazz){   
        T t = (T) newInstance(clazz);   
        Method[] methods = clazz.getMethods();   
           
        for(int i=0;i<methods.length;i++){   
            ProxyTag pt = methods[i].getAnnotation(ProxyTag.class);   
            if(pt == null){   
                continue;   
            }   
            ProxyBean pb = (ProxyBean) newInstance(pt.proxyClass());   
            t = (T) pb.bind(t, methods[i].getName());   
        }   
        return t;   
    }   
      
    private static Object newInstance(final Class clazz){   
        try {   
            Constructor cons = clazz.getConstructor();   
            return cons.newInstance(new Class[]{});   
        } catch (SecurityException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        } catch (NoSuchMethodException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        } catch (IllegalArgumentException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        } catch (InstantiationException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        } catch (IllegalAccessException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        } catch (InvocationTargetException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        }   
        return null;   
    }   
}  

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ProxyFactory {
       
       
        public static <T> T getProxyBean(Class<T> clazz){
                T t = (T) newInstance(clazz);
                Method[] methods = clazz.getMethods();
               
                for(int i=0;i<methods.length;i++){
                        ProxyTag pt = methods[i].getAnnotation(ProxyTag.class);
                        if(pt == null){
                                continue;
                        }
                        ProxyBean pb = (ProxyBean) newInstance(pt.proxyClass());
                        t = (T) pb.bind(t, methods[i].getName());
                }
                return t;
        }
       
        private static Object newInstance(final Class clazz){
                try {
                        Constructor cons = clazz.getConstructor();
                        return cons.newInstance(new Class[]{});
                } catch (SecurityException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (NoSuchMethodException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (InstantiationException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (InvocationTargetException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                return null;
        }
} 测试类:

  
package test2;   
  
public class ProxyClass extends ProxyBean{   
  
    public void after() {   
        System.out.println("after....");   
    }   
  
    public void before() {   
        System.out.println("before....");   
    }   
}  

package test2;

public class ProxyClass extends ProxyBean{

        public void after() {
                System.out.println("after....");
        }

        public void before() {
                System.out.println("before....");
        }
}
  
public class ProxyClass2 extends ProxyBean{   
  
    public void after() {   
        System.out.println("after2....");   
    }   
  
    public void before() {   
        System.out.println("before2....");   
    }   
}  

public class ProxyClass2 extends ProxyBean{

        public void after() {
                System.out.println("after2....");
        }

        public void before() {
                System.out.println("before2....");
        }
}   
public interface IDemo {   
    public void sayHello();   
    public void sayHello2();   
}  

public interface IDemo {
        public void sayHello();
        public void sayHello2();
}   
public class Demo implements IDemo{   
      
    @ProxyTag(proxyClass=ProxyClass.class)   
    public void sayHello(){   
        System.out.println("hello....");   
    }   
      
    @ProxyTag(proxyClass=ProxyClass2.class)   
    public void sayHello2(){   
        System.out.println("hello2....");   
    }   
}  

public class Demo implements IDemo{
       
        @ProxyTag(proxyClass=ProxyClass.class)
        public void sayHello(){
                System.out.println("hello....");
        }
       
        @ProxyTag(proxyClass=ProxyClass2.class)
        public void sayHello2(){
                System.out.println("hello2....");
        }
}
  
public class Test {   
  
    /**  
     * @param args  
     */  
    public static void main(String[] args) {   
           
        IDemo demo = ProxyFactory.getProxyBean(Demo.class);   
        demo.sayHello();   
        System.out.println("-----------------------------");   
        demo.sayHello2();   
  
    }   
  
}  

public class Test {

        /**
         * @param args
         */
        public static void main(String[] args) {
               
                IDemo demo = ProxyFactory.getProxyBean(Demo.class);
                demo.sayHello();
                System.out.println("-----------------------------");
                demo.sayHello2();

        }

}  
before....   
hello....   
after....   
-----------------------------   
before2....   
hello2....   
after2....  

before....
hello....
after....
-----------------------------
before2....
hello2....
after2....  
我没有看过spring的拦截器源码,不过实现原理上估计差不多,需要源码请下载附件  

我没有看过spring的拦截器源码,不过实现原理上估计差不多,需要源码请下载附件  
刚刚发现代码有点笔误的地方,容易让人误解,展示的代码已经修改过来了,附件里的代码请自己对照着修改一下  

刚刚发现代码有点笔误的地方,容易让人误解,展示的代码已经修改过来了,附件里的代码请自己对照着修改一下
proxytest.rar (7.6 KB)
下载次数: 234

gz-vps 发表于 2011-8-29 10:48 | 显示全部楼层
不错,把异常再抛出来,ProxyBean里面的before和after可以设计成接口注入到某个容器里面,再有一个applicationcontext的概念我觉得就蛮好了

找不到我 发表于 2011-8-29 10:48 | 显示全部楼层
我不明白为啥demo可以使用两次,也就是调用两次方法?准确的说就是为啥两次调用可以区分是用那个ProxyClass
demo.sayHello();   
        System.out.println("-----------------------------");   
        demo.sayHello2();   

难道是句代码可以注册多个代理?
t = (T) pb.bind(t, pb, methods[i].getName());





叫我小乖 发表于 2011-8-29 10:48 | 显示全部楼层
t42dw 写道
我不明白为啥demo可以使用两次,也就是调用两次方法?准确的说就是为啥两次调用可以区分是用那个ProxyClass

demo.sayHello();   
        System.out.println("-----------------------------");   
        demo.sayHello2();   

难道是句代码可以注册多个代理?
t = (T) pb.bind(t, pb, methods[i].getName());




请认真看invoke方法

有烟没火 发表于 2011-8-29 10:48 | 显示全部楼层
Cindy_Lee 写道
t42dw 写道

我不明白为啥demo可以使用两次,也就是调用两次方法?准确的说就是为啥两次调用可以区分是用那个ProxyClass

demo.sayHello();   
        System.out.println("-----------------------------");   
        demo.sayHello2();   

难道是句代码可以注册多个代理?
t = (T) pb.bind(t, pb, methods[i].getName());




请认真看invoke方法

哦,有递归...

曾经的小孩 发表于 2011-8-29 10:48 | 显示全部楼层
相当不错,注释很强大

yoyo 发表于 2011-8-29 10:49 | 显示全部楼层
ProxyTag pt = methods[i].getAnnotation(ProxyTag.class); 这句话有问题啊。。。

hxy 发表于 2011-8-29 10:49 | 显示全部楼层
jeho0815 写道
ProxyTag pt = methods[i].getAnnotation(ProxyTag.class); 这句话有问题啊。。。

啥问题 望指教

有烟没火 发表于 2011-8-29 10:49 | 显示全部楼层
      
    用这种吧 Method[] methods = clazz.getDeclaredMethods();
    少循环几次

木已 发表于 2011-8-29 10:49 | 显示全部楼层
baiweiyll 写道
      
    用这种吧 Method[] methods = clazz.getDeclaredMethods();
    少循环几次

呵呵很有道理,是我疏忽了
ygwilson 发表于 2012-8-7 23:18 | 显示全部楼层
顶。支持一下
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-3-29 18:36 , Processed in 0.154157 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表