- 浏览: 504721 次
- 性别:
- 来自: 广州
-
文章分类
最新评论
-
来这里学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 2250Integer类里面有如下一段 ... -
读源码之旅 java.io包
2010-01-28 16:11 2351对于下图,研究了一下常用的InputStream,ByteAr ... -
从自身体会谈一谈测试
2008-01-21 13:05 2012论坛上关于测试的帖子 ... -
The Contract for Equality[java]
2008-01-14 20:43 1617As we Know,The Java API documen ... -
来改善你的switch语句
2007-12-26 13:10 2843善用多态来改善你的switch语句 下面举的 ... -
url传递中文参数笔录
2007-12-21 19:35 4317url传递中文参数笔录 ... -
小心给servlet忽悠了
2007-12-05 18:53 2346你真的会写线程安全的s ... -
ThreadLocal浅解
2007-12-01 13:16 2318如果有看到spring的一些源码的同学都知道,Threa ... -
体会Observer/Observable模式
2007-11-23 19:20 3189在现在的项目中,后台有一块程序感觉用Observer/Obse ... -
Java 5.0多线程编程学习资料笔录
2007-11-23 13:33 3858对于Java 5.0多线程编程的学习,可以参考一下网上的下面的 ... -
关于ClassLoader工作机制小记
2007-11-06 23:06 2368类装载器就是寻找类或接口字节文件进行解析并构造JVM内部对象表 ... -
web应用程序开发须注意私自启动线程的问题
2007-11-04 01:25 3261web应用程序开发注意私自启动线程的问题 我们知道静态变量是 ... -
interrupt方法点滴记录
2007-10-25 21:02 28711、sleep方法与interrupt方法 假如线程A像下 ... -
wait方法是在什么时候结束
2007-10-23 11:07 2949wait方法是在什么时候结束 1、当notify方法执行时 ... -
synchronized 笔记
2007-10-18 11:04 2953synchronized 笔记 1、synchronized ... -
该用notify 方法还是notifyAll方法
2007-10-18 10:15 2322选择notify的话,因为要唤醒的线程比较少,程序处理速度当然 ... -
有趣而简单的两段代码
2007-09-04 20:40 2244假如你想写一个小程序,保证字符串首尾两个字符是一样的,你可以如 ... -
正则表达式[浅例学习]
2007-07-17 16:19 2144举下面一段代码: public\\s+void\\s+test ... -
熟悉一下几个常用的eclipse快捷键
2007-07-16 13:03 1912在论坛里看到一个帖子,是Godlikeme在这一个帖子写的 h ... -
线程间通信一小例学习
2007-06-16 13:41 3467wait:告诉线程放弃监视器并进入睡眠状态,直到其他线程进入同 ...
相关推荐
- **基于代理的AOP**:适用于接口的实现类。 - **基于类的AOP**:可以应用于任何Java类,无论是否实现了接口。 ##### 2.3 Spring Web Spring Web模块为Web应用程序提供了基础支持。它包括以下两个主要子模块: - ...
例如,研究AOP的代理机制可以让人明白如何在运行时动态地织入切面代码,而DI的实现则能揭示对象间的依赖是如何被自动管理的。 “工具”标签可能暗示了Spring与其他开发工具的集成,如数据库连接池(如HikariCP)、...
3 Android SqliteManager 源码.zip
内容概要:本文详细介绍了基于S7-200 PLC的煤矿排水系统智能控制方案,重点讨论了三台水泵(两台工作水泵和一台备用水泵)的联动与备援策略。系统通过超声波液位传感器实时监测水位,根据不同水位情况自动控制水泵的启停。具体而言,水位低时不启动水泵,水位介于中水位和高水位之间时启动1号水泵,水位超过高水位则启动1号和2号水泵共同工作。若1号或2号水泵出现故障,系统会自动启用3号备用水泵。此外,MCGS6.2组态画面用于实时监控水位和水泵状态,帮助操作员及时应对异常情况,确保矿井安全。 适合人群:从事煤矿自动化控制领域的技术人员、矿业工程管理人员及相关研究人员。 使用场景及目标:适用于需要提高煤矿排水系统自动化水平的场合,旨在提升矿井排水效率和安全性,减少人工干预,确保矿井生产安全。 其他说明:文中提到的技术方案不仅提高了排水系统的可靠性,还为未来的智能化矿山建设提供了有益借鉴。
scratch少儿编程逻辑思维游戏源码-灌篮之王.zip
scratch少儿编程逻辑思维游戏源码-飞翔马里奥(2).zip
scratch少儿编程逻辑思维游戏源码-火柴人大战 中世纪战争.zip
scratch少儿编程逻辑思维游戏源码-几何冲刺(2).zip
南京证券-低轨卫星互联网启动,天地一体通信迈向6G
nginx-1.20.1
sshpass-1.06-8.ky10.aarch
少儿编程scratch项目源代码文件案例素材-我的世界2D(更新北极).zip
通信行业专题研究:车载全息数字人——AI+Agent新场景,全息投影新方向-20231121-国盛证券-13页
内容概要:本文详细介绍了利用西门子S7-200 PLC和组态王软件构建的邮件分拣系统的具体设计方案和技术细节。首先,文中阐述了硬件部分的设计,包括光电传感器、传送带电机以及分拣机械臂的连接方式,特别是旋转编码器用于精确测量包裹位移的技术要点。接着,展示了PLC编程中的关键代码段,如初始化分拣计数器、读取编码器数据并进行位置跟踪等。然后,描述了组态王作为上位机软件的作用,它不仅提供了直观的人机交互界面,还允许通过简单的下拉菜单选择不同的分拣规则(按省份、按重量或加急件)。此外,针对可能出现的通信问题提出了有效的解决方案,比如采用心跳包机制确保稳定的数据传输,并解决了因电磁干扰导致的问题。最后,分享了一些现场调试的经验教训,例如为减少编码器安装误差对分拣精度的影响而引入的位移补偿算法。 适合人群:从事自动化控制领域的工程师或者对此感兴趣的初学者。 使用场景及目标:适用于需要提高邮件或其他物品自动分拣效率的企业或机构,旨在降低人工成本、提升工作效率和准确性。 其他说明:文中提到的实际案例表明,经过优化后的系统能够显著改善分拣性能,将分拣错误率大幅降至0.3%,并且日均处理量可达2万件包裹。
scratch少儿编程逻辑思维游戏源码-机械汽车.zip
内容概要:本文详细探讨了在连续介质中利用束缚态驱动设计并实现具有最大和可调谐手征光学响应的平面手征超表面的方法。文中首先介绍了comsol三次谐波和本征手性BIC(束缚态诱导的透明)两种重要光学现象,随后阐述了具体的手征超表面结构设计,包括远场偏振图、手性透射曲线、二维能带图、Q因子图和电场图的分析。最后,通过大子刊nc复现实验验证了设计方案的有效性,并对未来的研究方向进行了展望。 适合人群:从事光学研究的专业人士、高校物理系师生、对光与物质相互作用感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解手征超表面设计原理及其光学响应机制的研究人员,旨在推动新型光学器件的研发和技术进步。 其他说明:本文不仅展示了理论分析和模拟计算,还通过实验证明了设计方法的可行性,为后续研究奠定了坚实的基础。
少儿编程scratch项目源代码文件案例素材-位图冒险.zip
少儿编程scratch项目源代码文件案例素材-校园困境2.zip
少儿编程scratch项目源代码文件案例素材-兔子吃萝卜.zip
scratch少儿编程逻辑思维游戏源码-海洋战争.zip