cglib 代理类 自己equals自己 返回false
简单的cglib代理示例
普通的 Java 类
package cglib;
public class UserService {
public void saveUser(String username) {
System.out.println("Saving user: " + username);
}
}
使用代理类来增强 UserService
package cglib;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class UserServiceProxy implements MethodInterceptor {
private Object target;
public UserServiceProxy(Object target) {
this.target = target;
}
public Object createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 在方法执行前可以添加额外的逻辑
System.out.println("Before method: " + method.getName());
// 调用原始方法
Object result = method.invoke(target, args);
// 在方法执行后可以添加额外的逻辑
System.out.println("After method: " + method.getName());
return result;
}
}
调用
package cglib;
public class CglibMain {
public static void main(String[] args) {
UserService userService = new UserService();
// 创建代理类
UserService proxy = (UserService) new UserServiceProxy(userService).createProxy();
System.out.println(proxy.equals(proxy));
// 调用代理对象的方法
proxy.saveUser("John");
}
}
Before method: equals
After method: equals
false // 这里明显不符合我们的预期,自己equals自己 应该是为true才对
Before method: saveUser
Saving user: John
After method: saveUser
debug 发现:
来到equals方法的时候,this 是 UserService 类,obj 是cglib的代理类,所以为false
正确写法:
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 在方法执行前可以添加额外的逻辑
System.out.println("Before method: " + method.getName());
// 调用原始方法
Object result = methodProxy.invokeSuper(o, args);
// 在方法执行后可以添加额外的逻辑
System.out.println("After method: " + method.getName());
return result;
}
Before method: equals
After method: equals
true // 这里符合预期
Before method: saveUser
Saving user: John
After method: saveUser
修改代码过后:
通过栈帧可以看到,此时多了CGLIB$equals$1:-1, UserService$$EnhancerByCGLIB$$41629a0a
然后到java.lang.Object#equals方法时 this 和 obj 都是cglib 代理类,所以为true
然后我们来看下cglib代理类的equals方法和CGLIB$equals$1方法
通过arthas jad 命令反编译出cglib类的代码
public final boolean equals(Object object) {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
UserService$$EnhancerByCGLIB$$41629a0a.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
Object object2 = methodInterceptor.intercept(this, CGLIB$equals$1$Method, new Object[]{object}, CGLIB$equals$1$Proxy);
return object2 == null ? false : (Boolean) object2;
}
return super.equals(object);
}
final boolean CGLIB$equals$1(Object object) {
return super.equals(object);
}
总结
method.invoke(target, args): 这种方式使用 Java 反射机制直接调用目标对象的方法。这对于普通的 Java 类是完全适用的,但是它会绕过 CGLIB 的代理逻辑。如果您使用这种方式,代理类中的任何增强逻辑都将被忽略。
methodProxy.invokeSuper(proxy, args): 这种方式使用 CGLIB 提供的 MethodProxy 来调用目标对象的方法。这样做会触发代理类中的增强逻辑,允许您在方法执行前后添加额外的操作。这是使用 CGLIB 创建代理时的常见做法。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧