在 spring 中使用 cglib 的嵌套代理
Nested Proxy using cglib in spring
前言: 我想创建一个现有代理的代理(在spring中使用cglib包)
,就像我调用原始方法 class 两个代理的两个方法都先调用一样。它有任何意义吗?或者有可能吗?
问题: 当我创建第二个 enhancer
时,我得到了
java.lang.ClassFormatError-->Duplicate method name "newInstance" with signature "
异常。
示例代码如下
原版Class
public class OriginalClass {
public void print(){
System.out.println("MAIN METHOD");
}
}
创建两个代理
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();
}
}
预期结果如下(打印)
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$b306ed$$EnhancerByCGLIB$133919
真实场景
我想使用 BeanPostProcessors
和 cglib
在 spring 代理的所有 bean 上包装代理。例如,我想在所有 @transactional
方法上包装一个代理(在交易前后记录)。
更新:我更喜欢创建代理,而不是AOP。(AOP本身就是一个代理)
我找到了有效的解决方案,当在第二个增强器中使用 methodProxy.invoke()
而不是 methodProxy.invokeSuper()
时它会起作用,而且 firstProxy
需要传递给调用而不是o
对象和超类设置为原始对象,没有 newInstance 方法:
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();
}
}
结果:
METHOD INTERCEPTOR AT SECOND PROXY
METHOD INTERCEPTOR AT FIRST PROXY
MAIN METHOD
前言: 我想创建一个现有代理的代理(在spring中使用cglib包) ,就像我调用原始方法 class 两个代理的两个方法都先调用一样。它有任何意义吗?或者有可能吗?
问题: 当我创建第二个 enhancer
时,我得到了
java.lang.ClassFormatError-->Duplicate method name "newInstance" with signature "
异常。
示例代码如下
原版Class
public class OriginalClass {
public void print(){
System.out.println("MAIN METHOD");
}
}
创建两个代理
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();
}
}
预期结果如下(打印)
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$b306ed$$EnhancerByCGLIB$133919
真实场景
我想使用 BeanPostProcessors
和 cglib
在 spring 代理的所有 bean 上包装代理。例如,我想在所有 @transactional
方法上包装一个代理(在交易前后记录)。
更新:我更喜欢创建代理,而不是AOP。(AOP本身就是一个代理)
我找到了有效的解决方案,当在第二个增强器中使用 methodProxy.invoke()
而不是 methodProxy.invokeSuper()
时它会起作用,而且 firstProxy
需要传递给调用而不是o
对象和超类设置为原始对象,没有 newInstance 方法:
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();
}
}
结果:
METHOD INTERCEPTOR AT SECOND PROXY
METHOD INTERCEPTOR AT FIRST PROXY
MAIN METHOD