动态代理(JDK CGLIB)

2024-05-10 11:38
文章标签 动态 jdk 代理 cglib

本文主要是介绍动态代理(JDK CGLIB),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

静态代理,一个代理类只能代理一个接口,好处的简单、好实现、好理解,坏处呢,举个例子,我们知道Mybatis逆向工程会生成N多个Mapper接口文件,如果每个Mapper接口都造一个代理类出来,然后呢,每个代理类做的事情又都是一样的——获取session、解析crud语句、执行crud、处理结果、结束session。

难道我们对此就束手无策了吗?不,使用动态代理,我们可以只造一个轮子就能代理everything。

动态代理分两种:Java动态代理 和 CGLib,其中Java动态代理只能代理实现了接口的类,而CGLib则可以代理一个没有实现任何接口的类

1 JDK动态代理

实现InvocationHandler并重写invoke方法。

public interface Hello {void say(String name);
}
public class HelloImpl implements Hello {@Overridepublic void say(String name) {System.out.println("Hello! " + name);}
}
public class DynamicProxy implements InvocationHandler {//能代理任意一个类private Object target;public DynamicProxy(Object target) {this.target = target;}/*** 能接收任意数量和类型的参数、任意的返回值、任意的异常抛出* @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object result = method.invoke(target, args);after();return result;}private void before() {System.out.println("Before");}private void after() {System.out.println("After");}
测试一下:
public class Test {public static void main(String[] args) {Hello hello = new HelloImpl();DynamicProxy dynamicProxyHandler = new DynamicProxy(hello);Hello helloProxy = (Hello) Proxy.newProxyInstance(hello.getClass().getClassLoader(),hello.getClass().getInterfaces(),dynamicProxyHandler);helloProxy.say("biglong");}
}

 

打印出来是:
Before
Hello! biglong
After
——————————————— 割以咏志 ———————————————————————
以上Proxy.newProxyInstance的方法还是有点复杂,需要传入3个参数:

参数1:ClassLoader

参数2:该实现类的所有接口

参数3:动态代理对象

我们可以简化一下:

public class DynamicProxy2 implements InvocationHandler {...@SuppressWarnings("unchecked")public <T> T getProxy() {return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}...
}

测试下:

public class Test2 {public static void main(String[] args) {Hello hello = new HelloImpl();DynamicProxy2 dynamicProxy2 = new DynamicProxy2(hello);Hello helloProxy = dynamicProxy2.getProxy();helloProxy.say("biglong");}
}

输出跟上面一样。

2 CGLib动态代理

如果一个类没有实现任何接口,以上JDK动态代理就成了废物,此时CGLib粉墨登场,CGLib可以代理没有接口的类——我们的Spring框架的AOP就用了这个。

public class CGLibProxy implements MethodInterceptor {//单例模式(懒汉)private static CGLibProxy instance = new CGLibProxy();public static CGLibProxy getInstance() {return instance;}private CGLibProxy() {}@SuppressWarnings("unchecked")public <T> T getProxy(Class<T> cls) {return (T) Enhancer.create(cls, this);}@Overridepublic Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {before();Object result = proxy.invokeSuper(target, args);after();return result;}private void before() {System.out.println("Before");}private void after() {System.out.println("After");}
}

测试一下:

public class Test {public static void main(String[] args) {HelloImpl helloProxy = CGLibProxy.getInstance().getProxy(HelloImpl.class);helloProxy.say("biglong");}
}

 

 

 

这篇关于动态代理(JDK CGLIB)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/976333

相关文章

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S

Java JDK Validation 注解解析与使用方法验证

《JavaJDKValidation注解解析与使用方法验证》JakartaValidation提供了一种声明式、标准化的方式来验证Java对象,与框架无关,可以方便地集成到各种Java应用中,... 目录核心概念1. 主要注解基本约束注解其他常用注解2. 核心接口使用方法1. 基本使用添加依赖 (Maven

Python动态处理文件编码的完整指南

《Python动态处理文件编码的完整指南》在Python文件处理的高级应用中,我们经常会遇到需要动态处理文件编码的场景,本文将深入探讨Python中动态处理文件编码的技术,有需要的小伙伴可以了解下... 目录引言一、理解python的文件编码体系1.1 Python的IO层次结构1.2 编码问题的常见场景二

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

在macOS上安装jenv管理JDK版本的详细步骤

《在macOS上安装jenv管理JDK版本的详细步骤》jEnv是一个命令行工具,正如它的官网所宣称的那样,它是来让你忘记怎么配置JAVA_HOME环境变量的神队友,:本文主要介绍在macOS上安装... 目录前言安装 jenv添加 JDK 版本到 jenv切换 JDK 版本总结前言China编程在开发 Java

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

JAVA中安装多个JDK的方法

《JAVA中安装多个JDK的方法》文章介绍了在Windows系统上安装多个JDK版本的方法,包括下载、安装路径修改、环境变量配置(JAVA_HOME和Path),并说明如何通过调整JAVA_HOME在... 首先去oracle官网下载好两个版本不同的jdk(需要登录Oracle账号,没有可以免费注册)下载完

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注