AOP之JDK动态代理和CGLib动态代理

林炳文Evankaka原创作品。转载请注明出处

本文工程免费下载

一、JAVA动态代理1.1 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 按照代理的创建时期,代理类可以分为两种。 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

动态代理:在程序运行时,运用反射机制动态创建而成。

我们知道,通过使用代理,可以在被代理的类的方法的前后添加一些处理方法,这样就达到了类似AOP的效果。而JDK中提供的动态代理,就是实现AOP的绝好底层技术。

1.2 JDK动态代理 JDK动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。1.3 CGLib动态代理

还有一个叫CGLib的动态代理,CGLib全称为Code Generation Library,是一个强大的高性能,高质量的代码生成类库,可以在运行期扩展Java类与实现Java接口,CGLib封装了asm,可以再运行期动态生成新的class。和JDK动态代理相比较:JDK创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则可以通过CGLib创建动态代理

(以下代码来自Spring.3.x企业应用开发实战,其中有些地方笔者做了些增加)

二、JDK动态代理

1、接口ForumService

package aop;public interface ForumService {public void removeTopic(int topic);public void removeForum(int forumId);}2、ForumServiceImpl实现package aop;public class ForumServiceImpl implements ForumService{public void removeTopic(int topic){System.out.println("模拟删除记录"+topic);try{Thread.currentThread().sleep(20);}catch(Exception e){throw new RuntimeException(e);}}public void removeForum(int forumId){System.out.println("模拟删除记录"+forumId);try{Thread.currentThread().sleep(20);}catch(Exception e){throw new RuntimeException(e);}}}这里我们可以来看看上面的方法:

先测试下:

ForumServiceImpl forumServiceImpl=new ForumServiceImpl();forumServiceImpl.removeForum(190);forumServiceImpl.removeTopic(123);

接下来我们要实现在删除记录之前和之后增加一些方法

3、要在ForumServiceImpl.java中插入的增强方法

package aop;public class PerformanceMonitor {private static ThreadLocal<MethodPerformance> performanceRecord=new ThreadLocal<MethodPerformance>();public static void begin(String method){System.out.println("begin monitor..");MethodPerformance mp=new MethodPerformance(method);performanceRecord.set(mp);}public static void end(){System.out.println("end monitor…");MethodPerformance mp=performanceRecord.get();mp.printPerformance();}}

MethodPerformance.java是真正加入的方法

package aop;public class MethodPerformance {private long begin;private long end;private String serviceMethod;public MethodPerformance(String serviceMethod){this.serviceMethod=serviceMethod;this.begin=System.currentTimeMillis();}public void printPerformance(){end=System.currentTimeMillis();long elapse=end-begin;System.out.println(serviceMethod+"花费"+elapse+"毫秒");}} 4、JDK动态代理PerformanceHandler.javapackage aop;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class PerformanceHandler implements InvocationHandler {private Object target;public PerformanceHandler(Object object) {this.target = object;}@Overridepublic Object invoke(Object arg0, Method arg1, Object[] arg2)throws Throwable {PerformanceMonitor.begin(target.getClass().getName() + "."+ arg1.getName());Object obj = arg1.invoke(target, arg2);PerformanceMonitor.end();return obj;}}5、使用ForumServiceImpl target=new ForumServiceImpl();PerformanceHandler handler=new PerformanceHandler(target);ForumService proxy=(ForumService)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), handler);proxy.removeForum(23);proxy.removeTopic(678);System.out.println("end monitor…");

结果:

三、CGlib动态代理

1、CglibProxy.java

package aop;import java.lang.reflect.Method;import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor{private Enhancer enhancer=new Enhancer();public Object getProxy(Class clazz){enhancer.setSuperclass(clazz);enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object arg0, Method arg1, Object[] arg2,MethodProxy arg3) throws Throwable {PerformanceMonitor.begin(arg0.getClass().getName() + "."+ arg1.getName());Object obj = arg3.invoke(arg0, arg2);PerformanceMonitor.end();return obj;}}2、测试CglibProxy proxy2=new CglibProxy();ForumServiceImpl forumServiceImpl=(ForumServiceImpl)proxy2.getProxy(ForumServiceImpl.class);forumServiceImpl.removeForum(456);forumServiceImpl.removeTopic(987);System.out.println("end monitor…");3、结果:

四、JDK动态代理和CGLib的比较

我无所事事的度过了今天,是昨天死去的人们所期望的明天。

AOP之JDK动态代理和CGLib动态代理

相关文章:

你感兴趣的文章:

标签云: