- 浏览: 495570 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
来这里学java:
...
实战篇:设计自己的Annotation -
yushui2000:
突然想到一种方法,就是1、2、2、3、4、5作为5个球(类似彩 ...
一道算法题目,值得一看 -
wst0350:
理解力
实战篇:设计自己的Annotation -
yingzhor:
楼下的,你看看代码不就知道怎么验证了吗?这不是放在sessio ...
利用servlet生成简单的验证码 -
ming_7755:
妙用Commons良药<三>
大家都清楚Spring的AOP方面工作是很优秀,但是其内在的基础的东西,还是有一大部分不太了解的,其AOP大量用了ThreadLocal,这一个在前面已做了介绍了,还有一个比较重要的怎样用动态代理组装成AOP.
说到动态代理,有两种情况,第一种是有接口的情况下,你可以选择为jdk自带的动态代理的方式来编写程序,但你想要为一个实在的类编写动态代理的方式的话,这时候就必须选择一些开源的lib包啦.spring和hibernate选择了同样的CGlib包,具体表现在:Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制,Spring则是利用cglib来实现动态代理。
接下来我们就来看看动态代理这两个情况是怎样实现的吧.其实通过demo是比较容易理解一样东西的.所以打算写一个简单的例子来表达我的意思,大家都知道JavaEye社区可以发新帖子,可以修改自己的帖子,所以我们定义下面的一个接口.
当然,有接口啦,我们自然而然的为它写一个实现的类,作为演示并没有实质性的代码的:
因为一般情况下,你发布帖子和编辑要处在事务范围之内(假设的),所以我们新写下面的一个功能类TransactionManager,想让在postTopic和editTopic方法前后分别调用下面的beginTransaction和endTransaction方法.
剩下的问题就是,我们用方式把TransactionManager里面的两个方法织入到JavaEyeForumImpl类里面方法的合适的位置,很简单地,我们只需要写一个处理的Handler类,如下:
在上面的类中的invoke方法中,"Object obj = method.invoke(target, args);"前后的语句指定调用前该前做,调用后该做什么.
接下来,就是写一个测试类啦
测试类,请仔细看 Proxy.newProxyInstance这一个方法的第二个参数必须指定target.getClass().getInterfaces()这一个接口后,动态代理才能起效. 这是为什么说平时我们说jdk 中的动态代理有时候比较麻烦,那是还要指定特定的接口的原因.
测试代码运行结果如下:
接下来我们来看看怎样用CGLib来生成动态代理,首先把TestDynamicProxy.java和TransactionHandler.java两个类删除掉,免得影响视线嘛,呵呵;然后再新建一个CglibProxy代理类.
然后,我们再写一个测试类如下:
测试的结果如下:
参考资料:
http://www.nirvanastudio.org/java/cglib-指南.html cglib 指南
http://www.moon-soft.com/doc/45039.htm Java-AOP编程入门
http://www.iteye.com/topic/98178 [深入了解Java ClassLoader、Bytecode 、ASM、cglib]
说到动态代理,有两种情况,第一种是有接口的情况下,你可以选择为jdk自带的动态代理的方式来编写程序,但你想要为一个实在的类编写动态代理的方式的话,这时候就必须选择一些开源的lib包啦.spring和hibernate选择了同样的CGlib包,具体表现在:Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制,Spring则是利用cglib来实现动态代理。
接下来我们就来看看动态代理这两个情况是怎样实现的吧.其实通过demo是比较容易理解一样东西的.所以打算写一个简单的例子来表达我的意思,大家都知道JavaEye社区可以发新帖子,可以修改自己的帖子,所以我们定义下面的一个接口.
package lighter.iteye.com; public interface JavaEyeForum { void postTopic(int topicId); void editTopic(int topicId); }
当然,有接口啦,我们自然而然的为它写一个实现的类,作为演示并没有实质性的代码的:
package lighter.iteye.com; public class JavaEyeForumImpl implements JavaEyeForum { public void postTopic(int topicId) { System.out.println("发布帖子,帖子的ID号为:"+topicId); } public void editTopic(int topicId) { System.out.println("编辑帖子,帖子的ID号为:"+topicId); } }
因为一般情况下,你发布帖子和编辑要处在事务范围之内(假设的),所以我们新写下面的一个功能类TransactionManager,想让在postTopic和editTopic方法前后分别调用下面的beginTransaction和endTransaction方法.
package lighter.iteye.com; public class TransactionManager { public static void beginTransaction(String methodName){ System.out.println(methodName + "开始事务管理!"); } public static void endTransaction(String methodName){ System.out.println(methodName + "事务管理结束!\n"); } }
剩下的问题就是,我们用方式把TransactionManager里面的两个方法织入到JavaEyeForumImpl类里面方法的合适的位置,很简单地,我们只需要写一个处理的Handler类,如下:
package lighter.iteye.com; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class TransactionHandler implements InvocationHandler { private Object target; public TransactionHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { TransactionManager.beginTransaction(method.getName()); Object obj = method.invoke(target, args); TransactionManager.endTransaction(method.getName()); return obj; } }
在上面的类中的invoke方法中,"Object obj = method.invoke(target, args);"前后的语句指定调用前该前做,调用后该做什么.
接下来,就是写一个测试类啦
package lighter.iteye.com; import java.lang.reflect.Proxy; public class TestDynamicProxy { public static void main(String[] args) { JavaEyeForum target = new JavaEyeForumImpl(); TransactionHandler handler = new TransactionHandler(target); JavaEyeForum proxy = (JavaEyeForum) Proxy.newProxyInstance(target .getClass().getClassLoader(),target.getClass().getInterfaces(), handler); proxy.postTopic(100); proxy.editTopic(999); } }
测试类,请仔细看 Proxy.newProxyInstance这一个方法的第二个参数必须指定target.getClass().getInterfaces()这一个接口后,动态代理才能起效. 这是为什么说平时我们说jdk 中的动态代理有时候比较麻烦,那是还要指定特定的接口的原因.
测试代码运行结果如下:
引用
postTopic 开始事务管理!
发布帖子,帖子的ID号为:100
postTopic事务管理结束!
editTopic 开始事务管理!
编辑帖子,帖子的ID号为:999
editTopic事务管理结束!
发布帖子,帖子的ID号为:100
postTopic事务管理结束!
editTopic 开始事务管理!
编辑帖子,帖子的ID号为:999
editTopic事务管理结束!
接下来我们来看看怎样用CGLib来生成动态代理,首先把TestDynamicProxy.java和TransactionHandler.java两个类删除掉,免得影响视线嘛,呵呵;然后再新建一个CglibProxy代理类.
package lighter.iteye.com; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * net.sf.cglib.proxy.Enhancer和MethodInterceptor在CGLib中负责完成代理对象创建和方法截获处理, * 产生的是目标类的子类而不是通过接口来实现方法拦截的,Enhancer主要是用于构造动态代理子类来实现拦截,MethodInterceptor(扩展了 * Callback接口)主要用于实现around advice(AOP中的概念) */ public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz) { enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable { String methodName = obj.getClass().getName()+"."+method.getName(); TransactionManager.beginTransaction(methodName); Object result = proxy.invokeSuper(obj, args); TransactionManager.endTransaction(methodName); return result; } }
然后,我们再写一个测试类如下:
package lighter.iteye.com; public class TestCGLibProxy { public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); JavaEyeForum forum = (JavaEyeForum)proxy.getProxy(JavaEyeForumImpl.class); forum.postTopic(999); forum.editTopic(999); } }
测试的结果如下:
引用
lighter.iteye.com.JavaEyeForumImpl$$EnhancerByCGLIB$$155ad1e9.postTopic 开始事务管理!
发布帖子,帖子的ID号为:999
lighter.iteye.com.JavaEyeForumImpl$$EnhancerByCGLIB$$155ad1e9.postTopic事务管理结束!
lighter.iteye.com.JavaEyeForumImpl$$EnhancerByCGLIB$$155ad1e9.editTopic 开始事务管理!
编辑帖子,帖子的ID号为:999
lighter.iteye.com.JavaEyeForumImpl$$EnhancerByCGLIB$$155ad1e9.editTopic事务管理结束!
发布帖子,帖子的ID号为:999
lighter.iteye.com.JavaEyeForumImpl$$EnhancerByCGLIB$$155ad1e9.postTopic事务管理结束!
lighter.iteye.com.JavaEyeForumImpl$$EnhancerByCGLIB$$155ad1e9.editTopic 开始事务管理!
编辑帖子,帖子的ID号为:999
lighter.iteye.com.JavaEyeForumImpl$$EnhancerByCGLIB$$155ad1e9.editTopic事务管理结束!
参考资料:
http://www.nirvanastudio.org/java/cglib-指南.html cglib 指南
http://www.moon-soft.com/doc/45039.htm Java-AOP编程入门
http://www.iteye.com/topic/98178 [深入了解Java ClassLoader、Bytecode 、ASM、cglib]
发表评论
-
读源码之旅 有意思的Integer类
2010-02-01 09:33 2133Integer类里面有如下一段 ... -
读源码之旅 java.io包
2010-01-28 16:11 2274对于下图,研究了一下常用的InputStream,ByteAr ... -
从自身体会谈一谈测试
2008-01-21 13:05 1947论坛上关于测试的帖子 ... -
The Contract for Equality[java]
2008-01-14 20:43 1514As we Know,The Java API documen ... -
来改善你的switch语句
2007-12-26 13:10 2776善用多态来改善你的switch语句 下面举的 ... -
url传递中文参数笔录
2007-12-21 19:35 4224url传递中文参数笔录 ... -
小心给servlet忽悠了
2007-12-05 18:53 2260你真的会写线程安全的s ... -
ThreadLocal浅解
2007-12-01 13:16 2224如果有看到spring的一些源码的同学都知道,Threa ... -
体会Observer/Observable模式
2007-11-23 19:20 3130在现在的项目中,后台有一块程序感觉用Observer/Obse ... -
Java 5.0多线程编程学习资料笔录
2007-11-23 13:33 3800对于Java 5.0多线程编程的学习,可以参考一下网上的下面的 ... -
关于ClassLoader工作机制小记
2007-11-06 23:06 2271类装载器就是寻找类或接口字节文件进行解析并构造JVM内部对象表 ... -
web应用程序开发须注意私自启动线程的问题
2007-11-04 01:25 3165web应用程序开发注意私自启动线程的问题 我们知道静态变量是 ... -
interrupt方法点滴记录
2007-10-25 21:02 27631、sleep方法与interrupt方法 假如线程A像下 ... -
wait方法是在什么时候结束
2007-10-23 11:07 2870wait方法是在什么时候结束 1、当notify方法执行时 ... -
synchronized 笔记
2007-10-18 11:04 2858synchronized 笔记 1、synchronized ... -
该用notify 方法还是notifyAll方法
2007-10-18 10:15 2243选择notify的话,因为要唤醒的线程比较少,程序处理速度当然 ... -
有趣而简单的两段代码
2007-09-04 20:40 2164假如你想写一个小程序,保证字符串首尾两个字符是一样的,你可以如 ... -
正则表达式[浅例学习]
2007-07-17 16:19 2070举下面一段代码: public\\s+void\\s+test ... -
熟悉一下几个常用的eclipse快捷键
2007-07-16 13:03 1844在论坛里看到一个帖子,是Godlikeme在这一个帖子写的 h ... -
线程间通信一小例学习
2007-06-16 13:41 3394wait:告诉线程放弃监视器并进入睡眠状态,直到其他线程进入同 ...
相关推荐
java全套笔记 入门到实践 适合热爱java的人群 所有笔记 来自狂神说java
Java标准IO流编程一览笔录
市场产品现状 侦查询问笔录 产品现状 笔录的历史记录缺乏有效利用, 区域内的笔录不能共享 笔录生成缺乏法律库、经验库实时指导 笔录信息不能及时与公安业务 实时对接缺乏实战性 笔录记录时,人工打字效率慢 智能...
尽职调查访谈笔录
破产清算组询问笔录.pdf
java调用PageOffice V4.4实现在线编辑保存Word文件(支持跨浏览器)
刚开始,把java的学习记下来
现场勘验检查笔录(范文).pdf
律师庭审笔录(模板).pdf
一款功能强大的电子笔录软件,能大大提高笔录办公的效率,是不可多得的办公软件
笔录软件好用
安全生产事故调查询问笔录制作要求示范文本.pdf
厦门市公安局开发运用的公安笔录制作管理信息系统。
信访接待谈话笔录.pdf
律师调查笔录范例.doc
会议笔录ppt模板适用于行政工作主题设计应用。
律师庭审笔录(民事).pdf
【笔录执行官】是您记录思想与才华的利器,影响力显而易见!它能让您转瞬即失的奇思妙想记录在案;也是您记住心路历程的不二选择;也能让您大篇的写作不再觉得难以整理,使您思想的力量能挥洒自如,随心所欲!它可能...
调查笔录模板(单位通用).rar