当前位置: 首页 > wzjs >正文

网站建设合作分成合同建设门户网站的基本意义有哪些

网站建设合作分成合同,建设门户网站的基本意义有哪些,网站建设logo图片,网站页面图片1 已有JDK Dynamic Proxy,为什么还要CGLIB? JDK Dynamic Proxy 和 CGLib 是两种常用的代理技术,它们各自有不同的适用场景和局限性。在已经有了 JDK Dynamic Proxy 的情况下,还需要 CGLib 的原因: 1.1. 类 vs 接口 J…

1 已有JDK Dynamic Proxy,为什么还要CGLIB?

JDK Dynamic Proxy 和 CGLib 是两种常用的代理技术,它们各自有不同的适用场景和局限性。在已经有了 JDK Dynamic Proxy 的情况下,还需要 CGLib 的原因:


1.1. 类 vs 接口

JDK Dynamic Proxy 只能代理实现了接口的类。
它通过 java.lang.reflect.Proxy 类生成代理对象,要求目标类必须实现一个或多个接口。

CGLib 可以代理没有实现接口的类。
它通过字节码操作(使用 ASM 库)动态生成目标类的子类来实现代理。


1.2. 功能限制

JDK Dynamic Proxy 无法代理类中的私有方法、静态方法或 final 方法。
它只能代理接口中声明的方法。

CGLib 可以代理类中的非私有方法(包括 protected 和 public 方法),并且支持对类本身进行增强。


1.3. 字节码增强需求

CGLib 提供了更强大的字节码操作能力,适用于需要深度修改类行为的场景。
例如,AOP 框架中可能需要拦截构造函数调用或修改类的内部逻辑,这在 JDK Dynamic Proxy 中是无法实现的。

2 怎样使用CGLIB实现动态代理?

CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,它广泛应用于AOP框架中,如Spring AOP。CGLIB通过生成一个被代理类的子类来实现代理,从而避免了Java代理的接口限制。以下是使用CGLIB实现动态代理的基本步骤:


2.1添加依赖

如果你使用的是Maven项目,需要在pom.xml中添加CGLIB的依赖:

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

2.2创建被代理类

创建一个普通的Java类,这个类的方法将被代理。这里使用前面讲过的示例代码: BusinessCalculator.

public class BusinessCalculator implements Calculator {@Overridepublic Long add(Integer a, Integer b) {long result = 0;for(int i=0; i<100000000; i++) {result += i + a + b;}return result;}@Overridepublic Long subtract(Integer a, Integer b) {long result = 0;for(int i=0; i<100000000; i++) {result += i + a - b;}return result;}@Overridepublic Long multiply(Integer a, Integer b) {long result = 0;for(int i=0; i<100000000; i++) {result += i + a * b;}return result;}@Overridepublic Long divide(Integer a, Integer b) {long result = 0;for(int i=0; i<100000000; i++) {result += i + a / b;}return result;}
}

2.3实现MethodInterceptor接口

创建一个拦截器类,实现net.sf.cglib.proxy.MethodInterceptor接口,并重写intercept方法

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;public class BusinessCalculatorInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method: " + method.getName());// 调用原始方法Object result = proxy.invokeSuper(obj, args);System.out.println("After method: " + method.getName());return result;}
}

2.4. 创建代理对象

使用CGLIB的Enhancer类创建目标类的代理对象。
示例代码如下:

import net.sf.cglib.proxy.Enhancer;public class CglibProxyDemo {public static void main(String[] args) {// 创建Enhancer对象Enhancer enhancer = new Enhancer();// 设置目标类enhancer.setSuperclass(BusinessCalculator.class);// 设置回调函数enhancer.setCallback(new BusinessCalculatorInterceptor());// 创建代理对象BusinessCalculator proxyInstance = (BusinessCalculator) enhancer.create();// 调用代理对象的方法System.out.println("Result of add: " + proxyInstance.add(1, 2));System.out.println("Result of subtract: " + proxyInstance.subtract(5, 3));System.out.println("Result of multiply: " + proxyInstance.multiply(6, 7));System.out.println("Result of divide: " + proxyInstance.divide(8, 9));}}

注意事项
目标类不能为final:CGLIB通过生成目标类的子类来实现动态代理,因此目标类不能声明为final。
性能开销:CGLIB在运行时生成字节码,可能会带来一定的性能开销。


通过以上步骤,您可以成功使用CGLIB实现动态代理。

2.5 运行效果

我的运行环境是JDK17, 运行上面代码时抛出异常:

Exception in thread "main" java.lang.ExceptionInInitializerErrorat org.derek.CglibProxyDemo.main(CglibProxyDemo.java:9)
Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @4f2410acat net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:464)at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:339)at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:96)at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:94)at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:119)at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:294)at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:221)at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:174)at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:153)at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:73)... 1 more

这个错误是由于 Java 9 及以上版本引入的模块化系统(Java Platform Module System, JPMS)导致的。模块化系统对类的访问进行了严格的限制,而CGLIB尝试通过反射访问 java.lang 包中的类或方法,从而导致 java.lang.ClassFormatError。

解决方案:

  • IntelliJ IDEA

    1. 打开运行配置(Run Configurations)。

    2. 在 VM options 中添加 --add-opens java.base/java.lang=ALL-UNNAMED

添加上面的VM 参数后,运行效果如下:
 

"C:\Program Files\Java\jdk-17\bin\java.exe" --add-opens java.base/java.lang=ALL-UNNAMED " org.derek.CglibProxyDemo


Before method: add
After method: add
Result of add: 5000000250000000
Before method: subtract
After method: subtract
Result of subtract: 5000000150000000
Before method: multiply
After method: multiply
Result of multiply: 5000004150000000
Before method: divide
After method: divide
Result of divide: 4999999950000000

3 CGLIB 实现动态代理的原理?

CGLIB 实现动态代理的原理主要基于字节码生成技术。以下是其核心原理:

3.1. 子类生成

CGLIB 通过在运行时动态生成目标类的子类来实现代理。它会继承目标类,并重写其中的所有非 final 方法。
继承机制:CGLIB 创建的目标类的子类会覆盖父类的方法,从而可以在方法调用前后插入自定义逻辑。
限制条件:目标类不能是 final 类型,且方法不能是 final 或 static,因为这些方法无法被子类覆盖。

3.2. 拦截器回调

CGLIB 使用回调机制(如 MethodInterceptor)来拦截目标方法的调用。当代理对象的方法被调用时,实际执行的是子类中重写的方法,而该方法会通过回调机制将控制权交给拦截器。
核心接口:MethodInterceptor 是 CGLIB 提供的核心接口,开发者需要实现该接口的 intercept 方法。
拦截逻辑:在 intercept 方法中,可以添加方法调用前后的逻辑,并通过MethodProxy.invokeSuper 调用原始方法。

3.3. 字节码生成

CGLIB 基于 ASM(一个 Java 字节码操作框架)生成字节码。它会在运行时动态创建一个新的类,该类继承了目标类并实现了所需的代理逻辑。
字节码操作:CGLIB 会解析目标类的字节码结构,生成一个新的子类字节码,并加载到 JVM 中。
性能优化:由于字节码生成和加载的过程较为复杂,CGLIB 的初始化开销较大,但一旦生成完成,运行时性能较高。

3.4. Enhancer 工具类

CGLIB 提供了 Enhancer 类作为核心工具,用于创建代理对象。
设置父类:通过 enhancer.setSuperclass(Class) 指定目标类。
设置回调:通过 enhancer.setCallback(Callback) 设置拦截器。
创建代理:调用 enhancer.create() 方法生成代理对象

3.5. 方法调用流程

以下是 CGLIB 动态代理的方法调用流程:
用户调用代理对象的方法。
代理对象(实际上是目标类的子类)拦截该方法调用。
调用 MethodInterceptor.intercept 方法,执行拦截逻辑。
在拦截器中通过 MethodProxy.invokeSuper 调用目标类的原始方法。
返回结果给用户。

3.6 示例代码说明

结合上下文中的 BusinessCalculator 类的add方法:

public class BusinessCalculator {public Long add(Integer a, Integer b) {long result = 0;for (int i = 0; i < 100000000; i++) {result += i + a + b;}return result;}
}

GLIB 会生成一个 BusinessCalculator 的子类,

BusinessCalculator$$EnhancerByCGLIB$$9b8a9c45

子类中包含下面的代码:

public final Long add(Integer var1, Integer var2) {MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_0;}return var10000 != null ? (Long)var10000.intercept(this, CGLIB$add$0$Method, new Object[]{var1, var2}, CGLIB$add$0$Proxy) : super.add(var1, var2);}

子类会覆盖 add 方法,并在方法内部调用拦截器的 intercept 方法。
拦截器中可以通过 MethodProxy.invokeSuper 调用原始的 add 方法。

怎样查看所有生成的源文件?

// 启用CGLIB调试模式,将生成的字节码文件保存到指定目录
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "net\\cglib");

感兴趣的童鞋,可以添加上面的代码,查看生成的类的源文件。结构如下:

总结
CGLIB 的核心原理是通过字节码生成技术动态创建目标类的子类,并利用回调机制拦截方法调用。相比 JDK 动态代理(基于接口),CGLIB 更适合对没有实现接口的类进行代理,但在性能和灵活性上各有优劣。


文章转载自:

http://ZtAmIuYI.dpqqg.cn
http://ct3toLvj.dpqqg.cn
http://smKIt1NH.dpqqg.cn
http://ygSD0qbx.dpqqg.cn
http://ymcHPuSf.dpqqg.cn
http://veKhCSdn.dpqqg.cn
http://kXI9ZZKU.dpqqg.cn
http://i3wlqr2c.dpqqg.cn
http://7nsLJCI5.dpqqg.cn
http://cNOCstsh.dpqqg.cn
http://JfWxpcoT.dpqqg.cn
http://kB4YCdoY.dpqqg.cn
http://wFoeFJpj.dpqqg.cn
http://qbRm7Wtz.dpqqg.cn
http://h20s4zeh.dpqqg.cn
http://KGVx7727.dpqqg.cn
http://cWscRqt2.dpqqg.cn
http://5eiEr2Cj.dpqqg.cn
http://OBaZv2sd.dpqqg.cn
http://KkwXcjMk.dpqqg.cn
http://8v7wzPgC.dpqqg.cn
http://sV4XBSTp.dpqqg.cn
http://jcUotYO5.dpqqg.cn
http://8Jq6ugup.dpqqg.cn
http://28pMZfkU.dpqqg.cn
http://3enQoP8C.dpqqg.cn
http://IJf4SuLd.dpqqg.cn
http://fHGqPUxm.dpqqg.cn
http://OJIhZ2iI.dpqqg.cn
http://qo5THE4x.dpqqg.cn
http://www.dtcms.com/wzjs/636259.html

相关文章:

  • 仿百度百科网站源码电子商务网站优化方案
  • 机械模板网站灌南县城乡建设局网站
  • 建站宝盒自助建站系统做智能网站软件下载
  • 转运网站开发网站开发项目责任分配矩阵
  • 苏州网站优化找哪家wordpress到底是什么
  • 百度 网站 说明红色企业网站模板
  • 建旅游网站多少钱泰州高端网站建设
  • 网站建设入门教程网络团队建设
  • 企业网站备案需要什么wordpress 显示多媒体
  • 新兴县建设局网站网站icp备案要多久
  • 百度收录效果好的网站传奇类网页游戏排行榜
  • 做网站的开发软件是什么wordpress做一个网站404引导
  • 58同城青岛网站建设安全舆情监测平台
  • 电商网站对比如何创建网页模板
  • 汇算清缴在哪个网站做Wordpress文章页面小工具
  • 顺义做网站的公司做网页和网站一样吗
  • 东莞著名网站建设企业广告设计方案
  • 网站ui升级怎么做wordpress 网络公司
  • 网站建设案例资讯品牌网站建设方案
  • 网站关键字分析曲周企业做网站推广
  • pc端兼手机端网站模板路桥建设网站
  • 网上如何建网站卖量具西宁网站建设哪家好
  • dz论坛做分类网站自助建站帮助网
  • 中山网站软件品牌营销咨询
  • 泰安集团网站建设网页设计个人总结800字
  • 做书app下载网站有哪些内容商城网站设计需要哪些技术
  • 游戏网站logo制作小程序开发平台好牌子推荐
  • 网站后台的搭建嘉兴首页
  • 怎么在网站上做下载做网站租用那个服务器好
  • 简述网站设计的原则泉州手机网站开发