首页 > 代码库 > JDK动态代理
JDK动态代理
JDK 1.3以后,java提供了动态代理的技术,允许开发者在运行初期创建接口的代理实例。所谓代理即对某一实例的增强,对象在实例化的时候得到增强,增强过的实例即为代理实例,代理实例往往在运行的时候被动态增强。
JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类代码,动态地将横切逻辑和业务逻辑编织在一起。
而Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。下面通过一组实例演示如何使用JDK的动态代理。
FormService.java
public interface FormService { /** * 模拟论坛话题被删除 * @param topicId */ public void removeTopic(int topicId); /** * 模拟论坛被删除 * @param forumId */ public void removeForum(int forumId); }
FormServiceImpl.java
public class FormServiceImpl implements FormService { @Override public void removeTopic(int topicId) { System.out.println("模拟删除Topic记录:" + topicId); try { Thread.sleep(20); } catch (InterruptedException e) { throw new RuntimeException(); } } @Override public void removeForum(int forumId) { System.out.println("模拟删除Topic记录:" + forumId); try { Thread.sleep(40); } catch (InterruptedException e) { throw new RuntimeException(); } } }
PerformanceHandler.java
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class PerformanceHandler implements InvocationHandler { private Object target; public PerformanceHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { String methodName = target.getClass().getName() + "." + method.getName(); System.out.println("对" + methodName + "方法进行性能检测。"); long start = System.currentTimeMillis(); Object obj = method.invoke(target, params); long end = System.currentTimeMillis(); System.out.println(methodName +"方法用时:" + (end - start) + "毫秒。"); return obj; } }
测试类TestForProxy.java
import java.lang.reflect.Proxy; public class TestForProxy { public static void main(String[] args) { FormService forumService = new FormServiceImpl(); PerformanceHandler handler = new PerformanceHandler(forumService); FormService proxy = (FormService) Proxy.newProxyInstance( forumService.getClass().getClassLoader(), forumService.getClass().getInterfaces(),handler); proxy.removeForum(10); proxy.removeTopic(1012); } }
程序运行运行结果:
对org.proxy.jdkproxy.FormServiceImpl.removeForum方法进行性能检测。
模拟删除Topic记录:10
org.proxy.jdkproxy.FormServiceImpl.removeForum方法用时:40毫秒。
对org.proxy.jdkproxy.FormServiceImpl.removeTopic方法进行性能检测。
模拟删除Topic记录:1012
org.proxy.jdkproxy.FormServiceImpl.removeTopic方法用时:20毫秒。
在以上代码中,我们实现了InvocationHandler接口,该接口定义了一个invoke(Object proxy,Method method,Object[] params)的方法,proxy是最终生成的代理实例,一般不会用到;method是被代理目标实例的某个具体方法,通过他可以发起目标实例方法的反射调用;params是通过被代理实例某一具体方法的入参,在方法反射时使用它。
注意:JDK的动态代理是针对接口的代理,即增强目标类必须是实现了某一个或多个接口的类,其被增强的方法也必须是接口中的方法,之所以称之为动态代理是因为对实例的代理发生在运行期,另外代理还可以发生在编译期和装载期(需要特殊的编译器和装载器)。
本文出自 “埃文” 博客,请务必保留此出处http://wenshengzhu.blog.51cto.com/5151285/1599445
JDK动态代理