jdk动态代理和cglb动态代理

简介: jdk动态代理和cglb动态代理

概述

动态代理和静态代理都是代理模式的实现方式,其主要区别在于代理类生成的时机和方式。

静态代理是在编译时就确定了代理类的代码,在程序运行前就已经存在了代理类的class文件。代理类与委托类的关系在编译时就已经确定,因此被称为静态代理。在静态代理中,代理类需要实现与委托类相同的接口或者继承委托类的父类,以便能够对委托类进行代理操作。

动态代理是在程序运行时生成代理类的代码,代理类通过反射机制动态生成。动态代理不需要像静态代理一样实现与委托类相同的接口或继承委托类的父类,它可以实现任意接口。动态代理的优势在于,在代理类和委托类之间增加一个代理对象,可以更加灵活地控制委托类的行为。同时,也可以使得代码更加通用化,减少代码的重复性。

总体来说,静态代理只能代理一个委托类,而动态代理可以代理多个委托类。但是,由于动态代理的实现机制比较复杂,所以相比静态代理,动态代理的性能开销更大。而静态代理虽然只能代理一个委托类,但是因为它是在编译时生成代码,所以相对来说执行效率更高。

在程序运行阶段,在内存中动态生成代理类,被称为动态代理,目的是为了减少代理类的数量。解决代码复用的问题。

DK动态代理技术:只能代理接口。

CGLIB动态代理技术:CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。它既可以代理接口,又可以代理类底层是通过继承的方式实现的。性能比JDK动态代理要好。(底层有一个小而快的字节码处理框架ASM。)

JDK动态代理

一个接口和一个实现类

接口类==>jdk动态代理必须要有一个接口类

Proxy类全名:java.lang.reflect.Proxy。这是JDK提供的一个类(所以称为JDK动态代理)。主要是通过这个类在内存中生成代理类的字节码。

其中newProxyInstance()方法有三个参数:

  • 第一个参数:类加载器。在内存中生成了字节码,要想执行这个字节码,也是需要先把这个字节码加载到内存当中的。所以要指定使用哪个类加载器加载。
  • 第二个参数:接口类型。代理类和目标类实现相同的接口,所以要通过这个参数告诉JDK动态代理生成的类要实现哪些接口。
  • 第三个参数:调用处理器。这是一个JDK动态代理规定的接口,接口全名:java.lang.reflect.InvocationHandler。显然这是一个回调接口,也就是说调用这个接口中方法的程序已经写好了,就差这个接口的实现类了。

invoke 方法,用户调用代理对象的什么方法,实质上都是在调用处理器的

invoke 方法,通过该方法调用目标方法,它也有三个参数:

public Object invoke(Object proxy, Method method, Object[] args)
  1. 第一个参数为 Proxy 类类型实例,如匿名的 $proxy 实例
  2. 第二个参数为委托类的方法对象
  3. 第三个参数为委托类的方法参数
  4. 返回类型为委托类某个方法的执行结果

orderService

1. public interface orderService {
2. public void order();
3. }

orderServiceImp

1. public class orderServiceImp implements  orderService{
2. @Override
3. public void order() {
4.         System.out.println("order....");
5.     }
6. }

proxyOrderService

1. public class proxyOrderService {
2. public static void main(String[] args) {
3. orderServiceImp orderServiceImp = new orderServiceImp();
4. orderService o = (orderService)Proxy.newProxyInstance(orderServiceImp.class.getClassLoader(),
5.                 orderServiceImp.class.getInterfaces(), new InvocationHandler() {
6. @Override
7. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
8.                         orderServiceImp.order();
9. return null;
10.                     }
11.                 }
12.         );
13.         o.order();
14.     }
15. }

 

代码可以封装为以下:

1. public class proxy implements InvocationHandler {
2. 
3. private  orderService orderService;
4. 
5. public proxy(orderService orderService) {
6. this.orderService = orderService;
7.     }
8. 
9. @Override
10. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
11.         System.out.println("proxy");
12.         method.invoke(orderService,args);
13. return null;
14.     }
15. }
1. public class proxyOrderService {
2. public static void main(String[] args) {
3. orderServiceImp orderServiceImp = new orderServiceImp();
4. orderService o = (orderService)Proxy.newProxyInstance(orderServiceImp.class.getClassLoader(),
5.                 orderServiceImp.class.getInterfaces(), new proxy(orderServiceImp)
6.         );
7.         o.order();
8.     }
9. }

cglb动态代理

CGLIB既可以代理接口,又可以代理类。底层采用继承的方式实现。所以被代理的目标类不能使用final修饰。

和JDK动态代理原理差不多,在CGLIB中需要提供的不是InvocationHandler,而是:net.sf.cglib.proxy.MethodInterceptor

使用CGLIB,需要引入它的依赖:

1. <dependency>
2. <groupId>cglib</groupId>
3. <artifactId>cglib</artifactId>
4. <version>3.3.0</version>
5. </dependency>

准备一个接口(cglb可以不用接口哈),一个类

1. public interface orderService {
2. public void order();
3. }
1. public class orderServiceImp implements orderService {
2. @Override
3. public void order() {
4.         System.out.println("order....");
5.     }
6. }
1. public class test {
2. public static void main(String[] args) {
3. Enhancer enhancer = new Enhancer();
4. orderServiceImp orderServiceImp = new orderServiceImp();
5.         enhancer.setSuperclass(orderServiceImp.getClass());
6.         enhancer.setCallback(new MethodInterceptor() {
7. @Override
8. public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
9. Object invoke = method.invoke(target, objects);
10. return invoke;
11.             }
12.         });
13. orderServiceImp o =(orderServiceImp)enhancer.create();
14.         orderServiceImp.order();
15.     }
16. }

MethodInterceptor接口中有一个方法intercept(),该方法有4个参数:

第一个参数:代理对象

第二个参数:目标方法

第三个参数:目标方法调用时的实参

第四个参数:代理方法

对于高版本的JDK,如果使用CGLIB,需要在启动项中添加两个启动参数:

  • --add-opens java.base/java.lang=ALL-UNNAMED
  • --add-opens java.base/sun.net.util=ALL-UNNAMED

CGLIB使用步骤:

1、创建字节码增强器

2、设置目标对象

3、设置回调函数

4、创建代理对象

5、使用代理对象


相关文章
|
11月前
|
缓存 Java 数据库连接
分析JDK动态代理的实现
分析JDK动态代理的实现
68 0
|
3月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
22天前
|
设计模式 Java API
[Java]静态代理与动态代理(基于JDK1.8)
本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
17 0
[Java]静态代理与动态代理(基于JDK1.8)
|
1月前
|
Java
【编程进阶知识】静态代理、JDK动态代理及Cglib动态代理各自存在的缺点及代码示例
本文介绍了三种Java代理模式:静态代理、JDK动态代理和Cglib动态代理。静态代理针对特定接口或对象,需手动编码实现;JDK动态代理通过反射机制实现,适用于所有接口;Cglib动态代理则基于字节码技术,无需接口支持,但需引入外部库。每种方法各有优缺点,选择时应根据具体需求考虑。
20 1
|
3月前
|
Java API 开发者
Jdk动态代理为啥不能代理Class?
该文章主要介绍了JDK动态代理的原理以及为何JDK动态代理不能代理Class。
Jdk动态代理为啥不能代理Class?
|
3月前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
212 0
|
3月前
|
设计模式 Java C++
揭秘!JDK动态代理VS CGLIB:一场关于Java代理界的‘宫心计’,你站哪队?
【8月更文挑战第24天】Java 动态代理是一种设计模式,允许在不改动原类的基础上通过代理类扩展功能。主要实现方式包括 JDK 动态代理和 CGLIB。前者基于接口,利用反射机制在运行时创建代理类;后者采用继承方式并通过字节码技术生成子类实现类的代理。两者在实现机制、性能及适用场景上有明显差异。JDK 动态代理适用于有接口的场景,而 CGLIB 更适合代理未实现接口的类,尽管性能更优但存在一些限制。开发者可根据需求选择合适的代理方式。
176 0
|
5月前
|
设计模式 Java 程序员
java动态代理(JDK和cglib)
java动态代理(JDK和cglib)
30 0
|
5月前
|
设计模式 Java 程序员
java动态代理(JDK和cglib)
java动态代理(JDK和cglib)
40 0
|
5月前
|
缓存 Java Maven
JDK 动态代理
JDK 动态代理
28 0