Как получить cglib proxy из Spring?

186
14 марта 2018, 05:49

Я хочу перехватить метод следующего простого класса:

public class MessageWriter {
    public void writeMessage() {
        System.out.print("method");
    }
}

с помощью перехватчика методов CGLIB:

import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.print("Cglib ");
        Object res = method.invoke(obj, args); 
        System.out.print(" proxy!");
        return res;
    }
}

И я могу получить cglib прокси с помощью cglib Enchancer:

CglibInterceptor cglibInterceptor = new CglibInterceptor(target);
MessageWriter cgLibProxy = (MessageWriter) Enhancer.create(MessageWriter.class, cglibInterceptor);
System.out.println("\ncglib proxy: ");
cgLibProxy.writeMessage();

Этот код работает. Однако я не могу понять, как получить cglib прокси из org.springframework.aop.framework.ProxyFactory или из org.springframework.cglib.proxy.Enhancer.create(), т.е. cglib-proxy из Spring?

Если я пишу следующий код:

MessageWriter cgLibSpringProxy = (MessageWriter) org.springframework.cglib.proxy.Enhancer.create(MessageWriter.class, cglibInterceptor);

eclipse подчёркивает create красным:

UPD

Если более точно переформулировать мой вопрос, меня интересует, можно ли как-нибудь указать в коде, что нужно использовать именно CGlib прокси, в случае, если целевой класс реализует интерфейс? Ведь "по умолчанию , когда целевой объект, оснащаемый советом, реализует какой-то интерфейс, для создания экземпляров прокси целевого объекта Spring будет использовать динамический прокси JDK". Вроде как в конфигурационном файле для этого можно указать

<aop:config proxy-target-class="true">
    <!-- other beans defined here... -->
</aop:config>

а вот в коде это как-нибудь можно сделать? И вроде как у класса ProxyFactory есть метод setProxyTargetClass:

ProxyFactory pf = new ProxyFactory () ;
pf.setProxyTargetClass(true);

но по описанию в документации я всё-таки не поняла, ТОЧНО ли установка этого метода в true обязывает Spring использовать именно CGLIB для создания прокси? Вроде как нет? Из документации о ProxyConfig.setProxyTargetClass():)

Set this to "true" to force proxying for the TargetSource's exposed target class. If that target class is an interface, a JDK proxy will be created for the given interface. If that target class is any other class, a CGLIB proxy will be created for the given class.

Answer 1

На сколько я знаю, CGlib используется по умолчанию при создании прокси без интерфесов в Spring:

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
public class SpringAop {
    public static class Entity {
        public void soSomething() {
            System.out.println("doing something");
        }
    }
    public static class Handler implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            System.out.println("before calling method");
            Object returnedValue = methodInvocation.proceed();
            System.out.println("after calling method");
            return returnedValue;
        }
    }

    public static void main(String[] args) {
        Entity entity = new Entity();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(entity);
        proxyFactory.addAdvice(new Handler());
        Entity entityProxy = (Entity) proxyFactory.getProxy();
        entityProxy.soSomething();
    }
}

Дополнение:

Дело в том, что если цель (target) не имеет интерфейсов, то прокси будет создан через наследование от цели. Для этого будет использован cglib. В противном случае, применяется AspectJ.

READ ALSO
Лямбда выражения и java

Лямбда выражения и java

У меня возник вопрос , если использовать лямбда выражения в java , к примеру в stream api , то программы будут работать быстрее? Я просто где-то слышал...

150
Быстрое чтение данных

Быстрое чтение данных

У нас есть следующая конструкция, которая отвечает за чтение:

154
JavaFX Как сделать окно внутри окна

JavaFX Как сделать окно внутри окна

Доброго времени суток! Как на JavaFX сделать окно Window 2 внутри главного окна Window 1? Те

209
BroadcstReciver и AlarmManager

BroadcstReciver и AlarmManager

У меня такая задача, нужно через определенные отрезки времени обмениваться с сайтом информацией и в силу свое малого познания android я делаю...

136