Ce qui suit est la méthode d'écriture native de CGLib (implémentée à l'aide des classes du package net.sf.cglib.proxy.*)
class Foo {
public void fun1(){
System.out.println("fun1");
fun2();
}
public void fun2() {
System.out.println("fun2");
}
}
class CGlibProxyEnhancer implements MethodInterceptor{
public Object getProxy(Class clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.print("before ");
Object result = proxy.invokeSuper(obj,args);
return result;
}
}
public class Test {
public static void main(String[] args) {
CGlibProxyEnhancer pf = new CGlibProxyEnhancer();
Foo foo = (Foo) pf.getProxy(Foo.class);
foo.fun1();
}
}
Le résultat imprimé est :
before fun1
before fun2
Vous pouvez voir que même si fun2() est appelé via foo.fun1(), fun()2 peut toujours être proxy.
Mais si vous utilisez la méthode d'écriture de base de Spring AOP :
class Foo {
public void fun1() {
System.out.println("fun1");
fun2();
}
public void fun2() {
System.out.println("fun2");
}
}
class Before implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.print("before ");
}
}
public class TestCGLib {
public static void main(String[] args) {
Foo foo = new Foo();
BeforeAdvice advice = new Before();
ProxyFactory pf = new ProxyFactory();
pf.setOptimize(true);//启用Cglib2AopProxy创建代理
pf.setProxyTargetClass(true);
pf.setTarget(foo);
pf.addAdvice(advice);
Foo proxy = (Foo) pf.getProxy();
proxy.fun1();
}
}
Le résultat de sortie est :
before fun1
fun2
On peut voir que la méthode fun2 n'est pas proxy.
Pourquoi y a-t-il une telle différence ?
L'aop de Spring ne peut pas intercepter les appels de méthode internes. Spring signalera le bean de l'objet réel et le proxyBean après proxy a été amélioré avec des aspects :
.proxyBean est équivalent à :
avant
invoquer(haricot,méthode)
after
De cette façon, fun2 est en fait appelé par le bean réel (invoke utilise l'objet réel pour exécuter la méthode que vous souhaitez exécuter), il n'y a donc pas d'effet avant.
Lorsque vous utilisez réellement cglib, vous utilisez des beans proxy tout au long du processus