JDK动态代理
-
实现
InovactionHandler
接口1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 耗时统计 */ public class LogInvocationHandler implements InvocationHandler { private UserService userService; public LogInvocationHandler(UserService userService) { this.userService = userService; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long start = System.currentTimeMillis(); Object invoke = method.invoke(userService, args); long end = System.currentTimeMillis(); System.out.println(method.getName() + " 耗时: " + (end - start)); return invoke; } }
-
业务类与接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
public interface UserService { /** * 根据用户id查询用户名称 * * @param userId UserId * @return userName */ String getUserNameById(long userId); } import java.util.concurrent.TimeUnit; public class UserServiceImpl implements UserService { @Override public String getUserNameById(long userId) { try { //模拟数据库查询 TimeUnit.MICROSECONDS.sleep(2); } catch (InterruptedException e) { throw new RuntimeException(e); } return "proxy" + userId; } }
-
创建代理对象
1 2 3 4 5 6 7 8 9 10 11
public static void main(String[] args) { //输出生成的代理类 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); UserService userService = new UserServiceImpl(); LogInvocationHandler invocationHandler = new LogInvocationHandler(userService); UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler); System.out.println(userServiceProxy.getUserNameById(1)); //输出: getUserNameById 耗时: 2 // proxy1 }
-
生成的代理类Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
package com.sun.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements UserService { private static Method m1; private static Method m3; private static Method m2; private static Method m0; //构造方法 public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String getUserNameById(long var1) throws { try { return (String)super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m3 = Class.forName("com.github.xdshent.design.proxy.UserService").getMethod("getUserNameById", Long.TYPE); m2 = Class.forName("java.lang.Object").getMethod("toString"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
-
原理
$Proxy0
类实现了业务接口UserService
并且继承了java.lang.reflect.Proxy
$Proxy0
加载时类静态方法中通过反射获取了java.lang.Object
中的equals
、hashCode
、toString
以及业务对象中的getUserNameById
方法对应的Method
对象Proxy.newProxyInstance
在生成代理对象时会把传入的InvocationHandler
放入$Proxy0
的构造函数中- 生成的代理对象在通过业务接口
UserService
调用时会调用父类Proxy
的InvocationHandler h
字段, 进而进入用户所写的LogInvocationHandler
, 参数为:- 当前
$Proxy0
对象 - 第2步获取到的对应
Method
对象 - 方法参数
- 当前
-
图示
CGLIB动态代理
-
依赖
1 2 3 4 5
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
-
实现
MethodInterceptor
1 2 3 4 5 6 7 8 9 10 11 12
public class LogMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { long start = System.currentTimeMillis(); Object invoke = proxy.invokeSuper(obj, args); long end = System.currentTimeMillis(); System.out.println(method.getName() + " 耗时: " + (end - start)); return invoke; } }
-
创建代理对象
1 2 3 4 5 6 7 8 9 10
public static void main(String[] args) { //设置生成的class对象输出到当前目录 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./"); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(new LogMethodInterceptor()); UserServiceImpl userService = (UserServiceImpl)enhancer.create(); System.out.println(userService.getUserNameById(1)); }
-
生成的Class
FastClass机制根据方法签名获取对应的索引, 执行时根据索引找到对应的方法直接执行
- 代理类
- 代理类的FastClass
- 目标类FastClass
-
整体概览
-
调用流程