一文读懂Java中的动态代理 (3)

通过上面一段代码不知道你有没有明白生成的第一个代理类的ClassName为什么是$Proxy0。通过观察生成的class $Proxy0 extends Proxy implements CommonService,我们知道JDK的动态代理必须要针对接口,而上面一段代码也做了合法性检查

if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); }

然后就要往sun.misc.ProxyGenerator#generateProxyClass()方法里看了

private static final boolean saveGeneratedFiles = (Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles")); public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) { ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2); final byte[] var4 = var3.generateClassFile(); if (saveGeneratedFiles) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { try { // 省略... Files.write(var2, var4, new OpenOption[0]); return null; } catch (IOException var4x) { throw new InternalError("I/O exception saving generated file: " + var4x); } } }); } return var4; }

这里看到了为什么我们要在main方法一开始加上sun.misc.ProxyGenerator.saveGeneratedFiles配置就是为了让生成的代理class字节码落盘生成文件。

继续就是ProxyGenerator#generateClassFile()如何根据className、interfaces生成classfile的byte[]以及如何得到class对象java.lang.reflect.Proxy#defineClass0,有兴趣可以深入探究。

private static native Class<?> defineClass0(ClassLoader loader, String name, byte[] b, int off, int len); 注意事项

JDK的动态代理是不需要第三方库支持的,被代理的对象必须要实现接口。

CGLib

CGLib(Code Generation Library)是一个功能较为强大、性能也较好的代码生成包,在许多AOP框架中得到广泛应用。

快速入门

除了UserService、ProductService,还有订单业务(OrderService)也需要用代理模式添加统一日志处理,但是注意,OrderService并没有实现任何接口,且delete()方法用final修饰。

public class OrderService { public Object query(Long id) { String s = "查询到订单:" + id; System.out.println(s); return s; } public final void delete(Long id) { System.out.println("已删除订单:" + id); } }

我们知道,JDK的动态代理必须要求实现了接口,而cglib没有这个限制。具体操作如下:

(1) 引入cglib的maven依赖

<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>

(2) 编写方法拦截器

import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class LogInterceptor implements MethodInterceptor { private void preHandle() { System.out.println("开始处理请求时间: " + System.currentTimeMillis()); } private void postHandle() { System.out.println("结束处理请求时间: " + System.currentTimeMillis()); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // pre handle preHandle(); // Invoke the original (super) method on the specified object Object object = proxy.invokeSuper(obj, args); // post handle postHandle(); return object; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxyjj.html