首页 > 编程语言 >Java:SpringBoot实现JDK动态代理和CGLIB动态代理

Java:SpringBoot实现JDK动态代理和CGLIB动态代理

时间:2023-11-06 21:33:26浏览次数:41  
标签:Java target Object 代理 proxy import 动态 public

(目录)

需要代理的对象

// 接口
public interface PayService {
    void pay();
}

// 实现
public class AliPayService implements PayService {
    @Override
    public void pay() {
        System.out.println("AliPayService");
    }
}

1. JDK 动态代理

在 JDK 动态代理中,被代理类必须实现一个或多个接口,并通过 InvocationHandler 接口来实现代理类的具体逻辑。

实现 InvocationHandler

package com.example.demo.proxy.handler;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class LogInvocationHandler implements InvocationHandler {

   private Object target;

    public LogInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("log before invoke");

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

        System.out.println("log after invoke");
        return result;
    }
}

测试类

package com.example.demo.proxy;

import com.example.demo.proxy.handler.LogInvocationHandler;
import com.example.demo.proxy.impl.AliPayService;
import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class InvocationHandlerTests {
    @Test
    public void testLogInvocationHandler() {
        PayService payService = new AliPayService();
        
        // 创建一个代理类:通过被代理类、被代理实现的接口、方法调用处理器来创建
        PayService payServiceProxy = (PayService) Proxy.newProxyInstance(
                payService.getClass().getClassLoader(),
                new Class[]{PayService.class},
                new LogInvocationHandler(payService)
        );

        payServiceProxy.pay();
        // log before invoke
        // AliPayService
        // log after invoke
    }
}

2. CGLIB 动态代理

CGLIB 动态代理是一种使用 CGLIB 库来实现动态代理的技术。在 CGLIB 动态代理中,代理类不需要实现接口,而是通过继承被代理类来实现代理。

package com.example.demo.proxy.handler;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class LogMethodInterceptor implements MethodInterceptor {
    // 被代理对象
    private Object target;

    public LogMethodInterceptor(Object target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("log before invoke");

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

        System.out.println("log after invoke");
        return result;
    }
}

测试类

package com.example.demo.proxy;

import com.example.demo.proxy.handler.LogMethodInterceptor;
import com.example.demo.proxy.impl.AliPayService;
import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;

public class LogMethodInterceptorTests {

    @Test
    public void testLogMethodInterceptor() {
        PayService target = new AliPayService();

        PayService proxy = (PayService) Enhancer.create(
                target.getClass(),
                new LogMethodInterceptor(target)
        );

        proxy.pay();
        // log before invoke
        // AliPayService
        // log after invoke
    }
}

总结

实现方法 实现技术
JDK 动态代理 实现接口
CGLIB 动态代理 继承父类

参考文章

  1. 动态代理是如何实现的?
  2. JDK动态代理和CGLIB有什么区别?

标签:Java,target,Object,代理,proxy,import,动态,public
From: https://blog.51cto.com/mouday/8217941

相关文章

  • JAVA多线程并发查询百万数据的内存占用问题?
    在Java中使用多线程并发查询百万数据时,内存占用是一个需要考虑的重要问题。以下是一些解决该问题的方案:分批查询:将数据分成较小的批次进行查询,而不是一次性加载全部数据。这样可以减少每个线程需要处理的数据量,降低内存占用。可以将查询结果分组或按需加载,以保持内存占用的合理范......
  • java中 Calendar日历方法使用
    java中Calendar日历方法使用Calendar类抽象类Calendar提供了一组方法,允许把以毫秒为单位的时间转换成一些有用的时间组成部分。Calendar不能直接创建对象,但可以使用静态方法getInstance()获得代表当前日期的日历对象,如:Calendarcal=Calendar.getInstance(); Calen......
  • javaweb-- Mybatis参数传递
     Mybatis提供了ParamNameResolver类进行封装 传入多个参数时,mybatis会将参数封装成Map集合map.put("arg0",参数值1)map.put("param1",参数值1)map.put("arg1",参数值2)map.put("param2",参数值2) ......
  • java怎么去入门,用java怎么开发一个简单的安卓程序?
    Java是一种广泛使用的编程语言,特别适合于安卓应用开发。如果你想入门Java并使用它来开发安卓应用,你可以遵循以下步骤:入门Java学习Java的基础知识:数据类型、变量、运算符控制流(if/else语句、switch语句、循环)方法(函数)面向对象编程(类、对象、继承、多态性)异常处理集合框......
  • java接口实现是什么意思,通俗易懂的方式让你去理解,不信你看不懂
    Java接口(Interface)可以被理解为一个合约或者是一组规则。当一个类签署这样一个合约时,它就同意遵守这些规则,也就是实现这个接口中声明的所有方法。可以用一家餐厅来做一个比喻:假设“接口”是一家餐厅提供的菜单,菜单上列出了一系列的菜品,但是菜单上并没有说明这些菜品如何制作(即接......
  • java类是什么意思,给你做个比喻你就懂了,小白必看
     Java中的类(Class)可以比作是一个蓝图或者是一个模板,它用来创建具体的对象(Object)。类定义了一组属性和方法,对象则是根据这个蓝图创建出来的,拥有类中定义的属性和方法。做一个比喻:想象一下你有一个饼干模具,这个模具决定了饼干的形状、大小以及模具上的图案。在这个比喻中,饼干模......
  • java对象是什么意思,还有方法是什么,给你做个详细的比喻
     在Java编程语言中,“对象”和“方法”是面向对象编程(OOP)的两个基本概念。让我用一个比喻来解释这两个概念,然后给出一个简单的例子。对象(Object)想象一下一个真实世界中的机器,比如一辆汽车。一辆汽车可以看作是一个“对象”。它有一些特性,如品牌、颜色、车轮数量等,这些在编程中我......
  • java访问数据库的步骤,把每一步骤都讲解出来
    Java访问数据库通常是通过JDBC(JavaDatabaseConnectivity)API实现的。JDBC是一个JavaAPI,可以统一地访问各种关系型数据库。使用JDBC访问数据库的步骤如下:1.加载数据库驱动首先,需要加载你要连接的数据库对应的JDBC驱动。这一步通常通过调用Class.forName()方法实现。Class.for......
  • java如何生成一个随机数,并写出生成原理和执行过程
     在Java中,生成随机数通常可以通过以下几种方式:使用 Math.random() 方法使用 Random 类使用 SecureRandom 类(更安全的随机数)1.使用 Math.random() 方法Math.random() 方法返回一个 double 类型的值,范围在0.0(含)至1.0(不含)之间的随机数。这个方法实际上是 java.u......
  • java实现多线程执行的方法,举个简单的例子
    在Java中实现多线程可以通过以下两种主要方式:继承 Thread 类实现 Runnable 接口下面我将通过这两种方式分别提供一个简单的例子,并解释每一步的执行过程。继承 Thread 类这是通过创建 Thread 类的子类,并覆盖其 run 方法来实现的。//第一步:创建一个扩展自Thread......