英文:
Nested Proxy using cglib in spring
问题
前言:我想要创建一个已存在代理的代理(使用Spring中的cglib包),就像在我调用原始方法类时,两个代理的方法都会首先被调用。这有任何意义吗?或者可行吗?
问题:当我创建第二个enhancer
时,我会得到java.lang.ClassFormatError-->Duplicate method name "newInstance" with signature "
异常。
##示范代码如下
###原始类
public class OriginalClass {
public void print(){
System.out.println("MAIN METHOD");
}
}
###创建两个代理
public class Main {
public static void main(String[] args) {
//创建第一个代理
Enhancer firstEnhancer = new Enhancer();
firstEnhancer.setSuperclass(OriginalClass.class);
firstEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("METHOD INTERCEPTOR AT FIRST PROXY");
return methodProxy.invokeSuper(o, objects);
});
OriginalClass firstProxy = (OriginalClass) firstEnhancer.create();
//创建第二个代理
Enhancer secondEnhancer = new Enhancer();
secondEnhancer.setSuperclass(firstProxy.getClass());
secondEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("METHOD INTERCEPTOR AT SECOND PROXY");
return methodProxy.invokeSuper(o, objects);
});
//在这一行出现异常
OriginalClass secondProxy = (OriginalClass) secondEnhancer.create();
//调用
secondProxy.print();
}
}
###预期结果如下(打印)
METHOD INTERCEPTOR AT SECOND PROXY
METHOD INTERCEPTOR AT FIRST PROXY
MAIN METHOD
###但我得到了以下异常(在创建第二个代理时)
Caused by: java.lang.ClassFormatError: Duplicate method name "newInstance" with signature "([Lorg.springframework.cglib.proxy.Callback;)Ljava.lang.Object;" in class file com/test/OriginalClass$$EnhancerByCGLIB$$37b306ed$$EnhancerByCGLIB$$15133919
实际场景
我想要在所有被Spring代理的bean上创建一个代理,使用BeanPostProcessors
和cglib
。例如,我想要在所有@Transactional
方法上创建一个代理(在事务之前和之后进行日志记录)。
更新:我更喜欢创建代理,而不是AOP(AOP本身就是代理)。
英文:
Preface: I want to create a proxy of an existed proxy (Using cglib package in spring)
, like when I call the original method class both methods of both proxies called first. Does it make any sense at all? or is it possible?
Problem: When I'm creating the second enhancer
, i get the
java.lang.ClassFormatError-->Duplicate method name "newInstance" with signature "
exception.
##Sample code is as follows
###Original Class
public class OriginalClass {
public void print(){
System.out.println("MAIN METHOD");
}
}
###Create Two Proxies
public class Main {
public static void main(String[] args) {
//Create First Proxy
Enhancer firstEnhancer= new Enhancer();
firstEnhancer.setSuperclass(OriginalClass.class);
firstEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("METHOD INTERCEPTOR AT FIRST PROXY");
return methodProxy.invokeSuper(o, objects);
});
OriginalClass firstProxy = (OriginalClass) firstEnhancer.create();
//Create Second Proxy
Enhancer secondEnhancer= new Enhancer();
secondEnhancer.setSuperclass(firstProxy.getClass());
secondEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("METHOD INTERCEPTOR AT SECOND PROXY");
return methodProxy.invokeSuper(o, objects);
});
//Getting Exception on this line
OriginalClass secondProxy = (OriginalClass) secondEnhancer.create();
//Call
secondProxy.print();
}
}
###The expected result is as follows (Print)
METHOD INTERCEPTOR AT SECOND PROXY
METHOD INTERCEPTOR AT FIRST PROXY
MAIN METHOD
###But I get the below Exception (when creating the second proxy)
Caused by: java.lang.ClassFormatError: Duplicate method name "newInstance" with signature "([Lorg.springframework.cglib.proxy.Callback;)Ljava.lang.Object;" in class file com/test/OriginalClass$$EnhancerByCGLIB$$37b306ed$$EnhancerByCGLIB$$15133919
###Real World Scenario
I want to wrap a proxy on all beans that have been proxied by spring, using BeanPostProcessors
and cglib
. For example, I want to wrap a proxy on all @transactional
methods (log before and after the transactions).
Update: I prefer to create proxies, not AOPs.(AOP is itself a proxy)
答案1
得分: 3
我已找到可行的解决方案,在第二个增强器中使用 methodProxy.invoke()
而不是 methodProxy.invokeSuper()
,同时在调用中将 firstProxy
传递给调用,而不是 o
对象,并且将 superClass 设置为原始的那个,该类没有 newInstance
方法:
public class Test {
public static void main(String[] args) {
// 创建第一个代理
Enhancer firstEnhancer = new Enhancer();
firstEnhancer.setSuperclass(OriginalClass.class);
firstEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("第一个代理的方法拦截器");
return methodProxy.invokeSuper(o, objects);
});
OriginalClass firstProxy = (OriginalClass) firstEnhancer.create();
// 创建第二个代理
Enhancer secondEnhancer = new Enhancer();
secondEnhancer.setSuperclass(firstProxy.getClass().getSuperclass());
// secondEnhancer.setSuperclass(OriginalClass.class);
secondEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("第二个代理的方法拦截器");
return methodProxy.invoke(firstProxy, objects);
});
// 在这一行出现异常
OriginalClass secondProxy = (OriginalClass) secondEnhancer.create();
// 调用方法
secondProxy.print();
}
}
输出结果:
第二个代理的方法拦截器
第一个代理的方法拦截器
主方法
英文:
I've found working soultion, it works when used methodProxy.invoke()
instead of methodProxy.invokeSuper()
in the second enhancer, also the firstProxy
need to be passed to the invocation instead of the o
object and the superClass is set to the original one, that doesn't have the newInstance method:
public class Test {
public static void main(String[] args) {
//Create First Proxy
Enhancer firstEnhancer= new Enhancer();
firstEnhancer.setSuperclass(OriginalClass.class);
firstEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("METHOD INTERCEPTOR AT FIRST PROXY");
return methodProxy.invokeSuper(o, objects);
});
OriginalClass firstProxy = (OriginalClass) firstEnhancer.create();
//Create Second Proxy
Enhancer secondEnhancer= new Enhancer();
secondEnhancer.setSuperclass(firstProxy.getClass().getSuperclass());
// secondEnhancer.setSuperclass(OriginalClass.class);
secondEnhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
System.out.println("METHOD INTERCEPTOR AT SECOND PROXY");
return methodProxy.invoke(firstProxy, objects);
});
//Getting Exception on this line
OriginalClass secondProxy = (OriginalClass) secondEnhancer.create();
//Call
secondProxy.print();
}
}
result:
METHOD INTERCEPTOR AT SECOND PROXY
METHOD INTERCEPTOR AT FIRST PROXY
MAIN METHOD
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论