动态代理(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

相关文章

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

如何在Mac上安装并配置JDK环境变量详细步骤

《如何在Mac上安装并配置JDK环境变量详细步骤》:本文主要介绍如何在Mac上安装并配置JDK环境变量详细步骤,包括下载JDK、安装JDK、配置环境变量、验证JDK配置以及可选地设置PowerSh... 目录步骤 1:下载JDK步骤 2:安装JDK步骤 3:配置环境变量1. 编辑~/.zshrc(对于zsh

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S