一、JDK动态代理实现
接口
public interface UserService { void findAll(); }
实现类
public class UserServiceImpl implements UserService { public void findAll() { System.out.println("findAll。。。"); } }
定义一个代理类,并实现 InvocationHandler 接口
public class MyJdkProxy implements InvocationHandler { private Object target; /** * 绑定业务对象并返回一个代理类 */ public Object createProxy(Object target) { this.target = target; // 通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用 // 创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类 return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /** * 包装调用方法:进行预处理、调用后处理 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; System.out.println("预处理操作——————"); // 调用真正的业务方法 result = method.invoke(target, args); System.out.println("调用后处理——————"); return result; } }
测试类
public class Test { public static void main(String[] args) { MyJdkProxy jdkProxy = new MyJdkProxy(); UserService userService = (UserService) jdkProxy.createProxy(new UserServiceImpl()); userService.findAll(); } }
二、JDK动态代理,在什么时候执行invoke 方法?
我们再来一个测试,通过生成的代理类直接执行toString() 方法,发现invoke 方法也被调用了一次。那么这是为什么?是什么时候调用了invoke?
public static void main(String[] args) { MyJdkProxy jdkProxy = new MyJdkProxy(); UserService userService = (UserService) jdkProxy.createProxy(new UserServiceImpl()); userService.toString(); }
在MyJdkProxy 类中,生成代理类有一个核心方法 Proxy.newProxyInstance 方法
public Object createProxy(Object target) { this.target = target; // 通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用 // 创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); }
我们再来看一下这个 newProxyInstance 方法
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { // 如果目标代理类为空,抛出异常 if (h == null) { throw new NullPointerException(); } final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Look up or generate the designated proxy class. */ // 关键代码:生成接口的代理类的字节码文件 Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. * 通过反射获取构造函数对象并生成代理类实例 */ try { // 获取代理对象的构造方法(也就是$Proxy0(InvocationHandler h)) final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { // create proxy instance with doPrivilege as the proxy class may // implement non-public interfaces that requires a special permission return AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return newInstance(cons, ih); } }); } else { return newInstance(cons, ih); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } }
找到关键代码:Class<?> cl = getProxyClass0(loader, intfs);
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { // 限定代理的接口不能超过65535个 if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // If the proxy class defined by the given loader implementing // the given interfaces exists, this will simply return the cached copy; // otherwise, it will create the proxy class via the ProxyClassFactory // 关键代码:如果缓存中已经存在相应接口的代理类,直接返回;否则,使用ProxyClassFactory创建代理类 return proxyClassCache.get(loader, interfaces); }
这里 proxyClassCache 中一个 WeakCache 类型
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
再来看一下这个WeakCache 中的 get 方法
public V get(K key, P parameter) { Objects.requireNonNull(parameter); expungeStaleEntries(); Object cacheKey = CacheKey.valueOf(key, refQueue); // lazily install the 2nd level valuesMap for the particular cacheKey ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey); if (valuesMap == null) { ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } // create subKey and retrieve the possible Supplier<V> stored by that // subKey from valuesMap // 核心代码:当WeakCache中没有缓存相应接口的代理类,则会调用ProxyClassFactory类的apply方法来创建代理类 Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); Supplier<V> supplier = valuesMap.get(subKey); Factory factory = null; while (true) { if (supplier != null) { // supplier might be a Factory or a CacheValue<V> instance V value = supplier.get(); if (value != null) { return value; } } // else no supplier in cache // or a supplier that returned null (could be a cleared CacheValue // or a Factory that wasn't successful in installing the CacheValue) // lazily construct a Factory if (factory == null) { factory = new Factory(key, parameter, subKey, valuesMap); } if (supplier == null) { supplier = valuesMap.putIfAbsent(subKey, factory); if (supplier == null) { // successfully installed Factory supplier = factory; } // else retry with winning supplier } else { if (valuesMap.replace(subKey, supplier, factory)) { // successfully replaced // cleared CacheEntry / unsuccessful Factory // with our Factory supplier = factory; } else { // retry with current supplier supplier = valuesMap.get(subKey); } } } }
ProxyClassFactory 是Proxy的一个内部类,主要有一个apply 方法
private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // 代理类前缀 private static final String proxyClassNamePrefix = "$Proxy"; // 生成代理类名称的计数器 private static final AtomicLong nextUniqueNumber = new AtomicLong(); @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class<?> intf : interfaces) { /* * Verify that the class loader resolves the name of this * interface to the same Class object. * 校验类加载器是否能通过接口名称加载该类 */ Class<?> interfaceClass = null; try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from class loader"); } /* * Verify that the Class object actually represents an * interface. * 校验该类是否是接口类型 */ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /* * Verify that this interface is not a duplicate. * 校验接口是否重复 */ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } // 代理类包名 String proxyPkg = null; // package to define proxy class in /* * Record the package of a non-public proxy interface so that the * proxy class will be defined in the same package. Verify that * all non-public proxy interfaces are in the same package. * 非public接口,代理类的包名与接口的包名相同 */ for (Class<?> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { String name = intf.getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { throw new IllegalArgumentException( "non-public interfaces from different packages"); } } } if (proxyPkg == null) { // if no non-public proxy interfaces, use com.sun.proxy package // public代理接口,使用com.sun.proxy包名 proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } /* * Choose a name for the proxy class to generate. * 为代理类生成名字 */ long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; /* * Generate the specified proxy class. */ // 核心代码:真正生成代理类的字节码文件的地方 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces); try { // 使用类加载器将代理类的字节码文件加载到JVM中 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new IllegalArgumentException(e.toString()); } } }
仔细看这段代码,终于找到了其最核心的代码:
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces); // 生成字节码文件
编写测试类,并生成一个代理类的class文件
public class Test { public static void main(String[] args) { jdkTest(); createProxyClassFile(); } public static void jdkTest() { MyJdkProxy jdkProxy = new MyJdkProxy(); UserService userService = (UserService) jdkProxy.createProxy(new UserServiceImpl()); userService.hashCode(); } /** * 生成代理类.class文件 */ private static void createProxyClassFile() { // 设置生成.class文件名称 String name = "UserServiceProxy"; byte[] data = ProxyGenerator.generateProxyClass(name, new Class[] { UserService.class }); FileOutputStream out = null; try { out = new FileOutputStream(name + ".class"); // 打印hello文件所在目录,方便找到生成的 UserServiceProxy.class 文件 System.out.println((new File("hello")).getAbsolutePath()); out.write(data); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (null != out) try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }
用jd-jui 工具将生成的字节码反编译:
import com.service.UserService; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class UserServiceProxy extends Proxy implements UserService { private static Method m3; private static Method m1; private static Method m0; private static Method m2; public ProxySubject(InvocationHandler paramInvocationHandler) { super(paramInvocationHandler); } // UserService 中的 findAll() 方法 public final void findAll() { try { this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException error) { throw null; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final boolean equals(Object paramObject) { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (Error|RuntimeException error) { throw null; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (Error|RuntimeException error) { throw null; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)this.h.invoke(this, m2, null); } catch (Error|RuntimeException error) { throw null; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } static { try { m3 = Class.forName("com.service.UserService").getMethod("findAll", new Class[0]); m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); return; } catch (NoSuchMethodException noSuchMethodException) { throw new NoSuchMethodError(noSuchMethodException.getMessage()); } catch (ClassNotFoundException classNotFoundException) { throw new NoClassDefFoundError(classNotFoundException.getMessage()); } } }
我们发现这个类的 toString()、hashCode()、equals 以及 findAll() 方法都是通过 this.h.invoke(this, m1, null) 调用。其中 h 为 InvocationHandler 类型。
由此可总结:在使用jdk动态代理时,相当于会生成一个代理类 ***Proxy.class 文件(实际上并不生成文件,而是以字节码的形式直接加载到JVM中)