问题:

通过debug发现result.removeAll的时候 删不了

public boolean equals(Object obj) {
return obj instanceof OspSpringBoot2Initializer.OspBean && this.bean.equals(((OspSpringBoot2Initializer.OspBean)obj).bean);
}

this.bean.equals(((OspSpringBoot2Initializer.OspBean)obj).bean 这里返回了false



明明地址一致,那为什么返回了false?

定位问题:

进一步定位。



通过debug定位到: 最终调用java.lang.Object#equals方法的时候,this和obj的引用不一致所以返回false

通过栈帧可以看到:

调用了cglib增强类的equals方法

通过arthas jad 命令反编译出cglib类的代码

public final boolean equals(Object object) {
boolean[] arrbl = SalesNormalPoolService$$EnhancerByCGLIB$$e87bde91.$jacocoInit();
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor != null) {
arrbl[3] = true;
} else {
SalesNormalPoolService$$EnhancerByCGLIB$$e87bde91.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
arrbl[4] = true;
}
if (methodInterceptor != null) {
boolean bl;
Object object2 = methodInterceptor.intercept((Object)this, CGLIB$equals$0$Method, new Object[]{object}, CGLIB$equals$0$Proxy);
if (object2 == null) {
bl = false;
arrbl[5] = true;
} else {
bl = (Boolean)object2;
arrbl[6] = true;
}
arrbl[7] = true;
return bl;
}
arrbl[8] = true;
return super.equals(object);
}

这里结果依赖于methodInterceptor.intercept((Object)this, CGLIB$equals$0$Method, new Object[]{object}, CGLIB$equals$0$Proxy);

我们继续看下intercept 这个方法

public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//.. 省略 不会走这里的
}



发现是通过反射调用java.lang.Object#equals方法,此时是this.equals(args[0]) 发现地址不一致 结果返回false。

所以bug就定位到

method.invoke(this, args);

解决:

正确写法应该是:

methodProxy.invokeSuper(o, args);

public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return methodProxy.invokeSuper(o, args);
}
//.. 省略 不会走这里的
}

修改过后



在调用java.lang.Object#equals时



传入了o 和 args[0] ,它们两个地址相同,所以返回true

我们继续看下栈帧:



现在有调用CGLIB$equals$0:-1, SalesNormalPoolService$$EnhancerByCGLIB$$e87bde91

final boolean CGLIB$equals$0(Object object) {
boolean[] arrbl = SalesNormalPoolService$$EnhancerByCGLIB$$e87bde91.$jacocoInit();
arrbl[2] = true;
return super.equals(object);
}





也就是 现在的调用是:o == args[0] → true

以前的调用是:this == args[0] → false

cglib 代理类自己equals自己 返回false问题的更多相关文章

  1. spring查看生成的cglib代理类源码详解

    1.让程序阻塞(抛出异常会导致程序结束,所以在抛出异常之前阻塞) 2. windows控制台 cd到jdk目录下的lib目录,找到sa-jdi.jar 执行: java -classpath sa-j ...

  2. 从数据库取出两个同样的字符串用equals比较返回false

    1. 从网上搜索原因,大概总结为三点 1.1 取数据的两个数据库编码不一样,需要统一编码 1.2 字符类型不一样,可能一个为nchar一个为varchar 1.3 从数据库取出的数据有空格,需要tri ...

  3. JDK动态代理和cglib代理

    写一个简单的测试用例,Pig实现了Shout接口 public class MyInvocation implements InvocationHandler { Object k; public M ...

  4. Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现

    我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理.@pdai Spring框架系列 ...

  5. 关于Object类的equals方法和hashCode方法

    关于Object类的equals的特点,对于非空引用: 1.自反性:x.equals(x) return true : 2.对称性:x.equals(y)为true,那么y.equals(x)也为tr ...

  6. 分享知识-快乐自己:三种代理(静态、JDK、CGlib 代理)

    1):代理模式(静态代理)点我下载三种模式源码 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由 业务实现类.业务代理类 两部分组成 ...

  7. Java代理模式精讲之静态代理,动态代理,CGLib代理

    代理(Proxy)是一种设计模式,通俗的讲就是通过别人达到自己不可告人的目的(玩笑). 如图: 代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象 这三个代理模式,就 ...

  8. java动态代理类

    很有意思的一个东西,在java.lang.reflect包下 示例代码 package com.guangshan.test.proxy; import java.lang.reflect.Invoc ...

  9. CGLIB 和 JDK生成动态代理类的区别(转)

    文章转自http://luyuanliang.iteye.com/blog/1137292 AOP 使用的设计模式就是代理模式,是对IOC设计的补充.为了扩展性,往往会加上反射,动态生成字节码,生成代 ...

  10. JDK和CGLIB生成动态代理类的区别

     关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代 ...

随机推荐

  1. AI编程:cursor使用教程

    这是小卷对AI编程工具学习的第1篇文章,今天以cursor为例,通过给提示词,让不懂编程的小白也能自己用代码实现需求 1.什么是AI编程工具? 可以分为两类: 狭义的AI编程工具 面向程序员的,主要用 ...

  2. SqlServer性能检测之Sql语句排查

    很多时候,我们在用SQL语句查询数据时,难免会漏掉对SQL语句性能的考虑,所以有时就会造成SqlServer服务占用过高的问题,为了大致排查是哪些SQL语句造成的问题,我们可以通过如下SQL查询出最近 ...

  3. Lucas 定理证明与扩展

    Lucas 定理及其证明.扩展 \[\binom{n}{m}\equiv\binom{n/p}{m/p}\binom{n\bmod p}{m\bmod p}\pmod p,\text{where}\ ...

  4. 清华大学推出的 DeepSeek 从入门到精通(104页)免费教程!

    前言 最近 DeepSeek 的出现让 AI 在国内掀起了一股浪潮,各大媒体.平台都在讨论和推广 DeepSeek,帮助各行各样使用 AI 不再有困难.今天大姚给大家分享一个由清华大学推出的.免费的: ...

  5. 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!

    前言 腾讯元宝AI产品于2025年2月13日在应用商店发布更新,正式接入了DeepSeek R1模型,并宣布该模型已联网.满血上线,DeepSeek+腾讯混元,好用不卡机. 腾讯元宝介绍 腾讯元宝是依 ...

  6. Spring单元测试(一)入门与实践

    问题:如何快速测试,而不是每次测试都要重启应用? 目标:尽量只测试局部代码 不同的测试 软件工程中分为:单元测试.集成测试.功能测试.系统测试.其中功能测试和系统测试一般是测试人员的责任,但单元测试和 ...

  7. TensorFlow函数 tf.argmax()

    参数: input:输入数据 dimension:按某维度查找. dimension=0:按列查找: dimension=1:按行查找: 返回: 最大值的下标 import tensorflow.co ...

  8. CF145C Lucky Subsequence 题解

    首先,我们对这个幸运数进行分析,发现: \(10^9\) 以内只有 \(1023\) 个幸运数,即 \(\sum\limits_{i=0}^92^i\) 个. 考虑对幸运数和非幸运数分类讨论. 幸运数 ...

  9. 【技术美术】GPU渲染管线笔记

    [技术美术]GPU 渲染管线笔记 基本术语 基元.图面: 网格中所使用的顶点数据布局,常见的如点.线.三角面等,特殊的甚至包括一些带邻近基元的基元类型. 参数语义 语义是附加到着色器输入或输出参数的字 ...

  10. Mybatis中的 switch

    我这遇到个问题,如果 type字段为null则查询type is null,否则查对应的值 询问 AI 得知,可以用choose-when-otherwise <select> selec ...