锁定老帖子 主题:注解+动态代理的一个例子
精华帖 (1) :: 良好帖 (0) :: 新手帖 (6) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-03-14
最后修改:2011-03-16
在公司没事干了,学习下动态代理模式(关于代理的基础只是有很多帖子都有我就不重复了),做了个注解动态代理的例子,给那些学习注解或动态代理的初学者。 花了将近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(); } 代理类父类: 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; } } 测试类:
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 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 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.... 我没有看过spring的拦截器源码,不过实现原理上估计差不多,需要源码请下载附件 刚刚发现代码有点笔误的地方,容易让人误解,展示的代码已经修改过来了,附件里的代码请自己对照着修改一下 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-03-15
不错,把异常再抛出来,ProxyBean里面的before和after可以设计成接口注入到某个容器里面,再有一个applicationcontext的概念我觉得就蛮好了
|
|
返回顶楼 | |
发表时间:2011-03-15
demo.sayHello(); System.out.println("-----------------------------"); demo.sayHello2();
难道是句代码可以注册多个代理? t = (T) pb.bind(t, pb, methods[i].getName());
|
|
返回顶楼 | |
发表时间:2011-03-15
t42dw 写道
我不明白为啥demo可以使用两次,也就是调用两次方法?准确的说就是为啥两次调用可以区分是用那个ProxyClass
demo.sayHello(); System.out.println("-----------------------------"); demo.sayHello2();
难道是句代码可以注册多个代理? t = (T) pb.bind(t, pb, methods[i].getName());
请认真看invoke方法 |
|
返回顶楼 | |
发表时间:2011-03-16
Cindy_Lee 写道
t42dw 写道
我不明白为啥demo可以使用两次,也就是调用两次方法?准确的说就是为啥两次调用可以区分是用那个ProxyClass
demo.sayHello(); System.out.println("-----------------------------"); demo.sayHello2();
难道是句代码可以注册多个代理? t = (T) pb.bind(t, pb, methods[i].getName());
请认真看invoke方法
哦,有递归... |
|
返回顶楼 | |
发表时间:2011-03-16
相当不错,注释很强大
|
|
返回顶楼 | |
发表时间:2011-03-16
ProxyTag pt = methods[i].getAnnotation(ProxyTag.class); 这句话有问题啊。。。
|
|
返回顶楼 | |
发表时间:2011-03-16
jeho0815 写道 ProxyTag pt = methods[i].getAnnotation(ProxyTag.class); 这句话有问题啊。。。
啥问题 望指教 |
|
返回顶楼 | |
发表时间:2011-03-17
用这种吧 Method[] methods = clazz.getDeclaredMethods(); 少循环几次 |
|
返回顶楼 | |
发表时间:2011-03-17
baiweiyll 写道 用这种吧 Method[] methods = clazz.getDeclaredMethods(); 少循环几次 呵呵很有道理,是我疏忽了 |
|
返回顶楼 | |