Java JDK Proxy和CGLib动态代理示例讲解(jdkcglib动态代理区别)

  本篇文章为你整理了Java JDK Proxy和CGLib动态代理示例讲解(jdkcglib动态代理区别)的详细内容,包含有jdk动态代理原理 jdkcglib动态代理区别 jdk1.8动态代理 jdk的动态代理原理和cglib的动态代理 Java JDK Proxy和CGLib动态代理示例讲解,希望能帮助你了解 Java JDK Proxy和CGLib动态代理示例讲解。

  代理模式在Java中有很多应用场景,而代理又分静态代码和动态代理。静态代理是编写、编译或加载时织入代码实现,而动态代理则在运行时实现。简单而言,静态代理是在运行前就已经存在,而动态代理则在运行时才存在的。而常用的动态代理有两种实现:

  JDK Proxy: JDK Proxy是JDK自带的,不需要引入外部库,通过实现接口进行代理;

  CGLib: CGLib是引入第三方库,通过ASM技术来实现字节码的生成;通过继承的方式来实现。

  现在我们来通过代码分别展示一下两种方式。

  JDK Proxy

  JDK Proxy是通过实现接口来实现代理的,我们先定义一个接口:

  

public interface Flyable {

 

   String fly(String route);

  

 

  接着有一个实现类:

  

public class Bird implements Flyable {

 

   @Override

   public String fly(String route) {

   System.out.println("Route: " + route);

   return route;

  

 

  然后我们需要定义一个InvocationHandler来改动方法的逻辑,就是目标被代理后有什么不同:

  

public class FlyableInvocation implements InvocationHandler {

 

   private final Flyable target;

   public FlyableInvocation(Flyable target) {

   this.target = target;

   @Override

   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

   long start = System.nanoTime();

   System.out.println(target + ": ===JDK proxy===");

   Object result = method.invoke(this.target, args);

   System.out.println(target + ": ===JDK proxy===");

   long end = System.nanoTime();

   System.out.println("Executing time: " + (end - start) + " ns");

   return result;

  

 

  这里我们在方法调用前后加了日志,同时也计算了一下方法的执行时间。

  最终在调用的时候如下:

  

public class JDKDynamicProxy {

 

   public static void main(String[] args) {

   ClassLoader classLoader = JDKDynamicProxy.class.getClassLoader();

   Class ? [] interfaces = Bird.class.getInterfaces();

   Bird bird = new Bird();

   Flyable flyable = (Flyable) Proxy.newProxyInstance(classLoader, interfaces, new FlyableInvocation(bird));

   flyable.fly("Go to pkslow.com");

  

 

  通过Proxy.newProxyInstance方法会生成一个代理的实例,执行这个实例的方法,而原有实例bird被代理了。

  执行结果如下:

  

com.pkslow.basic.jdk.Bird@3551a94: ===JDK proxy===

 

  Route: Go to pkslow.com

  com.pkslow.basic.jdk.Bird@3551a94: ===JDK proxy===

  Executing time: 18195736 ns

  

 

  查看代理类

  我们还可以查看生成的代理类,可以通过添加VM参数:

  

# JDK 8

 

  -Dsum.misc.ProxyGenerator.saveGeneratedFiles=true

  # JDK 11

  -Djdk.proxy.ProxyGenerator.saveGeneratedFiles=true

  

 

  当然,也可以在Java代码中设置系统属性来实现。

  设置完成,再执行程序,就会生成代理类的.class文件。

  CGLib

  CGLib是通过继承来实现的,我们先来定义一个类:

  

public class Animal {

 

   public String talk(String str) {

   System.out.println("Talking: " + str);

   return str;

  

 

  然后定义一个Interceptor,这个类的作用就是生成代理实例,且定义如何改变目标方法的执行:

  

public class CGLibProxy T implements MethodInterceptor {

 

   private T target;

   public T getInstance(T target) {

   this.target = target;

   Enhancer enhancer = new Enhancer();

   enhancer.setSuperclass(this.target.getClass());

   enhancer.setCallback(this);

   return (T) enhancer.create();

   @Override

   public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

   long start = System.nanoTime();

   System.out.println(target + ": ===CGLib proxy===");

   Object result = methodProxy.invoke(this.target, args);

   System.out.println(target + ": ===CGLib proxy===");

   long end = System.nanoTime();

   System.out.println("Executing time: " + (end - start) + " ns");

   return result;

  

 

  这里同样是在方法前后加了日志,同时记录时长。

  调用如下:

  

public class CGLibDynamicProxy {

 

   public static void main(String[] args) {

   System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/larry/IdeaProjects/pkslow-samples/java-basic/jdk-cglib-proxy/target/cglib_proxy_classes");

   CGLibProxy Animal cgLibProxy = new CGLibProxy ();

   Animal animal = cgLibProxy.getInstance(new Animal());

   animal.talk("Hi, pkslow");

  

 

  这里设置系统属性是为了把生成的代理类输出到.class文件中,方便学习查看。

  执行结果如下:

  

com.pkslow.basic.cglib.Animal@57855c9a: ===CGLib proxy===

 

  Talking: Hi, pkslow

  com.pkslow.basic.cglib.Animal@57855c9a: ===CGLib proxy===

  Executing time: 28396871 ns

  

 

  JDK Proxy本质上使用的是反射的机制,而CGLib使用的是ASM,CGLib速度会更好。但它们都不支持final的类和方法,因为通过接口和继承都无法改变final方法。

  代码请看GitHub: https://github.com/LarryDpk/pkslow-samples

  以上就是Java JDK Proxy和CGLib动态代理示例讲解(jdkcglib动态代理区别)的详细内容,想要了解更多 Java JDK Proxy和CGLib动态代理示例讲解的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: