Das Folgende ist die native Schreibmethode von CGLib (implementiert mithilfe der Klassen im Paket 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();
}
}
Das gedruckte Ergebnis lautet:
before fun1
before fun2
Sie können sehen, dass fun2() zwar über foo.fun1() aufgerufen wird, fun()2 jedoch weiterhin als Proxy verwendet werden kann.
Aber wenn Sie die grundlegende Schreibmethode von Spring AOP verwenden:
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();
}
}
Das Ausgabeergebnis ist:
before fun1
fun2
Es ist ersichtlich, dass die fun2-Methode kein Proxy ist.
Warum gibt es so einen Unterschied?
spring的aop无法拦截内部方法调用,spring 会报存真实对象的 bean 以及 代理后的 proxyBean,proxyBean进行了切面增强处理:
proxyBean 相当于:
before
invoke(bean,method)
after
这样处理就导致实际上 fun2 是实际的 bean 去调用的(invoke就是使用实际对象执行你要执行的方法),所以,没有 before 效果。
而你实际使用 cglib 则全程都是用的是代理 bean