问题:

通过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. android主线程与子线程

    创建子线程创建子线程 更多关于java线程的文章可以查看这两篇 线程1 创建线程的方法 在android中穿件子线程的方案很简单 创建子线程的几种方法 ///////第一种/////// class ...

  2. Netty实战入门教程

    概述 Netty 是一个异步的.基于事件驱动的网络应用框架,用于快速开发可维护.高性能的网络服务器和客户端 Netty 在 Java 网络应用框架中的地位就好比:Spring 框架在 JavaEE 开 ...

  3. [BZOJ5093] 图的价值 题解

    考虑计算一个点的贡献,最后 \(\times n\) 即为所求. 显然一个点的贡献为 \(\sum\limits_{i=0}^{n-1}\binom{n-1}ii^k2^{\frac{(n-1)(n- ...

  4. Hadoop - [04] 分布式部署

    Zookeeper的分布式部署 >> Hadoop的分布式部署 一.集群规划 主机名 node01 node02 node03 JDK ○ ○ ○ Zookeeper ○ ○ ○ Name ...

  5. Vulkan环境配置 | vscode+msvc 解决方案

    Vulkan环境配置 | vscode+msvc 解决方案 前言 如果作为Windows 11侠的你是一个vscode爱好者,凑巧电脑上还安装有Visual Studio,这个时候你突然想配置一个Vu ...

  6. pandas 如何移动列的位置

    实现效果 原来备注列在第二列 代码: mid=df['备注'] #取备注列的值 df.pop('备注') #删除备注列 df.insert(4,'备注',mid) #插入备注列

  7. 基于近红外与可见光双目摄像头的人脸识别与活体检测,文末附Demo

    基于近红外与可见光双目摄像头的活体人脸检测原理 人脸活体检测(Face Anti-Spoofing)是人脸识别系统中的重要一环,它负责验证捕捉到的人脸是否为真实活体,以抵御各种伪造攻击,如彩色纸张打印 ...

  8. vue2打包部署到nginx,解决路由history模式下页面空白问题

    项目使用的是vue2,脚手架vue-cli 4. 需求:之前项目路由使用的是hash,现在要求调整为history模式,但是整个过程非常坎坷,遇到了页面空白问题.现在就具体讲一下这个问题. 首先,直接 ...

  9. 扩展知识:vscode配置easyx

    扩展知识:vscode配置easyx 前言 ‍ 因为个人用习惯了vscode,对于visual studio的操作只能说相当程度上很不适应,因此,我打算经历一番配置,让vscode可以配置上easyx ...

  10. kali安装pdtm工具

    kali安装pdtm工具 前言 今天想安装一下pdtm工具集的,但过程中一直出现各种错误,找了几篇文章之后并没有找到解决方法,后解决之后写了这样一篇文章希望可以解决大家在安装过程中碰到的部分问题 介绍 ...