How do I get a cglib proxy from Spring?
I want to intercept the method of the following simple class:
public class MessageWriter {
public void writeMessage() {
System.out.print("method");
}
}
Using the CGLIB method interceptor:
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;
}
}
And I can get a cglib proxy using cglib Enchancer:
CglibInterceptor cglibInterceptor = new CglibInterceptor(target);
MessageWriter cgLibProxy = (MessageWriter) Enhancer.create(MessageWriter.class, cglibInterceptor);
System.out.println("\ncglib proxy: ");
cgLibProxy.writeMessage();
This code works. However, I can't figure out how to get a cglib proxy from org.springframework.aop.framework.ProxyFactory
or from org.springframework.cglib.proxy.Enhancer.create()
, i.e. a cglib proxy from Spring?
If I write the following code:
MessageWriter cgLibSpringProxy = (MessageWriter) org.springframework.cglib.proxy.Enhancer.create(MessageWriter.class, cglibInterceptor);
Eclipse highlights create
red:
UPD
To more accurately reformulate my question, I am interested in is there any way to specify in the code that it is necessary to use a CGlib proxy, if the target class implements the interface? After all, " by default, when a target object equipped with a board implements some interface, Spring will use a dynamic JDK proxy to create proxy instances of the target object." Sort of like in in the configuration file, you can specify
<aop:config proxy-target-class="true">
<!-- other beans defined here... -->
</aop:config>
But is there any way to do this in the code? And it seems like the ProxyFactory
class has a {[10] method]}:
ProxyFactory pf = new ProxyFactory () ;
pf.setProxyTargetClass(true);
But according to the description in the documentation, I still did not understand whether setting this method in true
EXACTLY obliges Spring to use CGLIB to create a proxy? Like, no? From the documentation about 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.
3 answers
As far as I know, CGlib
is used by default when creating a proxy without interfaces in 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();
}
}
Addition:
The fact is that if the target (target
) has no interfaces, then the proxy will be created through inheritance from the target. To do this, cglib
will be used. Otherwise, AspectJ
is applied.
The @Scope annotation allows you to specify how to create a proxy. You can force the use of CGLIB, even if the class has an interface. Like this:
@Service
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyService impements SomeInterface { ... }
I have this code working:
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
// ...
Model model = new Model(1, "test");
MethodInterceptor callback = (object, method, args, methodProxy) -> methodProxy.invoke(model, args);
Model proxy = (Model) Enhancer.create(Model.class, callback);
assertThat(proxy).isEqualTo(model);