Вложенный прокси с помощью cglib весной - PullRequest
0 голосов
/ 15 марта 2020

Предисловие : я хочу создать прокси для существующего прокси (используя пакет 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

Сценарий реального мира

Я хочу обернуть прокси на всех бинах, которые были проксированы весной, используя BeanPostProcessors и cglib. Например, я хочу использовать прокси для всех методов @transactional (ведение журнала до и после транзакций).

Обновление : я предпочитаю создавать прокси , не АОП (АОП сам по себе прокси)

1 Ответ

1 голос
/ 15 марта 2020

Я нашел рабочую сущность, она работает при использовании 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
...