首页 > 其他分享 >CGLIB动态代理

CGLIB动态代理

时间:2023-06-10 13:32:58浏览次数:25  
标签:System 代理 proxy CGLIB UserService 动态 public

1. 引入依赖  102

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

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

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

2. 具体实现  102

我们准备一个没有实现接口的类,如下:

package com.powernode.proxy.service;

/**
 * 目标类  CGLIB动态代理  102
 **/
public class UserService {

    // 目标方法
    public boolean login(String username, String password){
        System.out.println("系统正在验证身份...");
        if ("admin".equals(username) && "123".equals(password)) {
            return true;
        }
        return false;
    }

    // 目标方法
    public void logout(){
        System.out.println("系统正在退出...");
    }
}

使用CGLIB在内存中为UserService类生成代理类,并创建对象:

package com.powernode.proxy.client;

import com.powernode.proxy.service.TimerMethodInterceptor;
import com.powernode.proxy.service.UserService;
import net.sf.cglib.proxy.Enhancer;

//CGLIB动态代理  102
public class Client {
    public static void main(String[] args) {
        // 创建字节码增强器对象
        // 这个对象是CGLIB库当中的核心对象,就是依靠它来生成代理类。
        Enhancer enhancer = new Enhancer();

        // 告诉CGLIB父类是谁。告诉CGLIB目标类是谁。
        enhancer.setSuperclass(UserService.class);

        // 设置回调(等同于JDK动态代理当中的调用处理器。InvocationHandler)
        // 在CGLIB当中不是InvocationHandler接口,是方法拦截器接口:MethodInterceptor
        enhancer.setCallback(new TimerMethodInterceptor());

        // 创建代理对象
        // 这一步会做两件事:
        // 第一件事:在内存中生成UserService类的子类,其实就是代理类的字节码。
        // 第二件事:创建代理对象。
        // 父类是UserService,子类这个代理类一定是UserService
        UserService userServiceProxy = (UserService) enhancer.create();

        // 建议大家能够把CGLIB动态代理生成的代理对象的名字格式有点印象。
        // 根据这个名字可以推测框架底层是否使用了CGLIB动态代理
        System.out.println(userServiceProxy);

        // 调用代理对象的代理方法。
        boolean success = userServiceProxy.login("admin", "123");
        System.out.println(success ? "登录成功" : "登录失败");

        userServiceProxy.logout();
    }
}


// 底层本质
//class UserService$$EnhancerByCGLIB$$82cb55e3 extends UserService{}

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

编写MethodInterceptor接口实现类:

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

第一个参数:目标对象

第二个参数:目标方法

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

第四个参数:代理方法

package com.powernode.proxy.service;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * CGLIB动态代理  102
 **/
public class TimerMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // 前面增强
        long begin = System.currentTimeMillis();

        // 怎么调用目标对象的目标方法呢?
        Object retValue = methodProxy.invokeSuper(target, objects);

        // 后面增强
        long end = System.currentTimeMillis();
        System.out.println("耗时"+(end - begin)+"毫秒");

        return retValue;
    }
}

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

CGLIB动态代理_代理类

● --add-opens java.base/java.lang=ALL-UNNAMED

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

CGLIB动态代理_System_02

标签:System,代理,proxy,CGLIB,UserService,动态,public
From: https://blog.51cto.com/u_15784725/6454477

相关文章

  • IXFH4N100Q-ASEMI代理艾赛斯MOS管IXFH4N100Q
    编辑:llIXFH4N100Q-ASEMI代理艾赛斯MOS管IXFH4N100Q型号:IXFH4N100Q品牌:IXYS/艾赛斯封装:TO-247最大漏源电流:4A漏源击穿电压:1000VRDS(ON)Max:3Ω引脚数量:3工作温度:-55℃~150℃沟道类型:N沟道MOS管、高压MOS管IXFH4N100Q特点低栅极电荷和电容-更易于驾驶-更快的切换国际标准包装RDS低(打开)无......
  • IXFH4N100Q-ASEMI代理艾赛斯MOS管IXFH4N100Q
    编辑:llIXFH4N100Q-ASEMI代理艾赛斯MOS管IXFH4N100Q型号:IXFH4N100Q品牌:IXYS/艾赛斯封装:TO-247最大漏源电流:4A漏源击穿电压:1000VRDS(ON)Max:3Ω引脚数量:3工作温度:-55℃~150℃沟道类型:N沟道MOS管、高压MOS管IXFH4N100Q特点低栅极电荷和电容-更易于驾驶-更快的切换国际标......
  • mybatis-动态构建SQL
    又学习到了,今天翻着队友写的代码,我看到了个注解,起初还以为是自定义的,我搜了下才发现,竟然是mybatis自带的这个注解,我竟然不知道,又是孤陋寡闻的一天,记录一下这个注解。查找了下这个注解发现这个注解是四个:我看了下与@Select有啥区别,这个@SelectProvider是能够加多条件判断的,看下面......
  • IXFA14N85XHV-ASEMI代理艾赛斯MOS管IXFA14N85XHV
    编辑:llIXFA14N85XHV-ASEMI代理艾赛斯MOS管IXFA14N85XHV型号:IXFA14N85XHV品牌:IXYS/艾赛斯封装:TO-263最大漏源电流:14A漏源击穿电压:850VRDS(ON)Max:550mΩ引脚数量:3沟道类型:N沟道MOS管特性:高功率密度、易于安装、节省的空间芯片材质:封装尺寸:如图特性:高压MOS管、N沟道MOS管工作结温:-55℃~1......
  • IXFA14N85XHV-ASEMI代理艾赛斯MOS管IXFA14N85XHV
    编辑:llIXFA14N85XHV-ASEMI代理艾赛斯MOS管IXFA14N85XHV型号:IXFA14N85XHV品牌:IXYS/艾赛斯封装:TO-263最大漏源电流:14A漏源击穿电压:850VRDS(ON)Max:550mΩ引脚数量:3沟道类型:N沟道MOS管特性:高功率密度、易于安装、节省的空间芯片材质:封装尺寸:如图特性:高压MOS管、N沟道MOS管......
  • 用户代理使用
    简介UserAgentUtils是JavaWeb项目中一个非常常用的工具库,用于解析用户浏览器的User-Agent字符串,以获取所访问的设备类型、操作系统类型和版本、浏览器类型和版本等信息。依赖<dependency><groupId>eu.bitwalker</groupId><artifactId>User......
  • 【01-动态规划-01背包问题】
    第一部分什么是动态规划?"动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。由于动态规划并不是某种具体的算法,而是一种解决特定问题的方法,因此它会出现在各式各样的数据结构中,与之相关的题目种类也更为繁杂。在OI中,计数等非最优化问题的递推解......
  • Python+tkinter动态创建与销毁组件小案例
    本文代码演示了如何在tkinter窗体上动态创建组件以及销毁组件的方法。importtkinterimporttkinter.messageboximporttkinter.simpledialogbtnList=[]#动态创建组件,并计算组件在窗体上的位置defplace(n):foriinrange(n):exec('btn'+str(i)+'=tkinter.B......
  • 动态代理:应用、好处
             ......
  • 动态代理:创建、工作流程演示
     packageKarl.Demo.DaiLi;publicclassTest{publicstaticvoidmain(String[]args){BigStars=newBigStar("杨超越");Starstar=ProxyUtil.createProxy(s);Stringrs=star.sing("好日子");System.out.prin......