开发者社区> 问答> 正文

在Spring使用cglib的嵌套代理

前言:我想创建一个现有代理的代理(在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) {

        //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$$37b306ed$$EnhancerByCGLIB$$15133919

现实世界场景 我想包装上已经由Spring代理,利用一切豆类代理BeanPostProcessors和cglib。例如,我想在所有@transactional方法上包装一个代理(在事务之前和之后记录日志)。

更新:我更喜欢创建代理而不是AOP。(AOP本身是代理)

问题来源:Stack Overflow

展开
收起
montos 2020-03-25 09:31:54 609 0
1 条回答
写回答
取消 提交回答
  • 我已经找到了可行的方案,它可以在第二个增强器中使用methodProxy.invoke()而不是methodProxy.invokeSuper()第二个增强器中使用,还firstProxy需要传递给调用而不是o对象,并且将superClass设置为原始的,没有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
    

    回答来源:Stack Overflow

    2020-03-25 09:32:42
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧 立即下载
微服务架构模式与原理Spring Cloud开发实战 立即下载
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载

相关实验场景

更多