Proxy 是设计模式中的一种。当须要在已存在的 class 上添加或修改功能时,能够经过建立 proxy object 来实现java
一般 proxy object 和被代理对象拥有相同的方法,而且拥有被代理对象的引用,能够调用其方法程序员
代理模式应用场景包括面试
代理有两种实现方式sql
对于重复性工做,如打印日志,静态代理须要为每一个 class 都建立 proxy class,过程繁琐和低效,而动态代理经过使用反射在运行时生成 bytecode 的方式来实现,更加方便和强大设计模式
由于 JDK 自带的 Dynamic proxy 只可以代理 interfaces,所以被代理对象须要实现一个或多个接口。架构
先来看一些概念:并发
proxy interface
proxy class 实现的接口proxy class
运行时建立的代理 class,并实现一个或多个 proxy interfaceproxy instance
proxy class 的实例InvocationHandler
每一个 proxy instance 都有一个关联的 invocation handler,当调用 proxy 对象的方法时,会统一封装,并转发到 invoke()
方法InvocationHandler 接口的定义以下分布式
package java.lang.reflect; public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
只定义了一个方法 invoke()
,参数含义以下ide
Object proxy
生成的代理对象Method method
调用的方法,类型为 java.lang.reflect.Method
Object[] args
调用方法的参数,array of objects简单来讲就是,调用 proxy object 上的方法,最终都会转换成对关联 InvocationHandler
的 invoke()
方法的调用高并发
能够使用 java.lang.reflect.Proxy
的静态方法 newProxyInstance
来建立 Proxy object
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { ... }
参数说明
使用动态代理打印方法的执行耗时
定义代理接口
public interface Foo { String doSomething(); }
实现接口
public class FooImpl implements Foo { @Override public String doSomething() { return "finished"; } }
定义 InvocationHandler,target 为被代理对象的引用,在方法执行完后打印耗时
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class TimingInvocationHandler implements InvocationHandler { private Object target; public TimingInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long start = System.nanoTime(); Object result = method.invoke(target, args); long elapsed = System.nanoTime() - start; System.out.println(String.format("Executing %s finished in %d ns", method.getName(), elapsed)); return result; } }
测试
import org.junit.Test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class DynamicProxyTest { @Test public void test() { ClassLoader cl = DynamicProxyTest.class.getClassLoader(); Class[] interfaces = new Class[]{Foo.class}; FooImpl fooImpl = new FooImpl(); InvocationHandler timingInvocationHandler = new TimingInvocationHandler(fooImpl); Foo foo = (Foo) Proxy.newProxyInstance(cl, interfaces, timingInvocationHandler); foo.doSomething(); } }
执行完会打印相似
Executing doSomething finished in 23148 ns
生成 proxy class 的一些属性和细节
分享免费学习资料
针对于Java程序员,我这边准备免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)
为何某些人会一直比你优秀,是由于他自己就很优秀还一直在持续努力变得更优秀,而你是否是还在知足于现状心里在窃喜!但愿读到这的您能点个小赞和关注下我,之后还会更新技术干货,谢谢您的支持!
资料领取方式:加入Java技术交流群963944895
,点击加入群聊,私信管理员便可免费领取