原生CGLib内部方法互相调用时可以代理,但基于CGLib的Spring AOP却代理失效,为什么?
下面是CGLib的原生写法(使用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();
}
}
打印结果是:
before fun1
before fun2
可以看到,虽然fun2()是通过foo.fun1()调用的,但fun()2依然能被代理。
但如果用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();
}
}
输出结果是:
before fun1
fun2
可见fun2方法没有被代理。
为什么会有这样的差异?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
spring的aop无法拦截内部方法调用,spring 会报存真实对象的 bean 以及 代理后的 proxyBean,proxyBean进行了切面增强处理:
proxyBean 相当于:
before
invoke(bean,method)
after
这样处理就导致实际上 fun2 是实际的 bean 去调用的(invoke就是使用实际对象执行你要执行的方法),所以,没有 before 效果。
而你实际使用 cglib 则全程都是用的是代理 bean
springaop在MethodInterceptor的实现类的intercept的方法中调用的不是proxy.invokeSuper(obj,args);此处obj是代理对象,而是proxy.invoke(target,args);此处target为原始对象,你的那个改成proxy.invoke(new Foo(),args);运行结果就一样了。
CGLib的原生写法那个 代码,你把
两者的运行就一样了