征服.刘华强 2013-10-28 23:13
浏览 637
已采纳

Spring 与 Cglib代理的诡异问题

一个普通的业务对象 没有实现接口 通过cglib代理
[code="java"]public class UserDao {

public void a() {
    System.out.println("aa");
}

public void b() {
    System.out.println("bb");
}

public void c() {
    this.a();
    this.b();
}

}[/code]

这是实现了cglib的一个接口 以完成方法的拦截
[code="java"]public class T implements MethodInterceptor{

@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
        MethodProxy arg3) throws Throwable {
    System.out.println("before");
    return arg3.invokeSuper(arg0, arg2);
}

}[/code]

[code="java"]
public static void main(String[] args) {
Enhancer en = new Enhancer();
en.setSuperclass(UserDao.class);
en.setCallbacks(new Callback[]{new T()});
UserDao dao = (UserDao) en.create();
dao.c();
}
[/code]
//这是通过CGLIB代理的测试 输出结果如下
before
before
aa
before
bb
每个方法都被拦截了 接下来问题来了

[code="java"] public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-aop.xml");
UserDao dao = (UserDao) beanFactory.getBean("userdao");
dao.c();
}[/code]

[code="java"] public void actionAop() {
System.out.println("ControllerAopHandler.actionAop()");
}[/code]

[code="java"]

<aop:config>
    <aop:aspect id="controllerAspect" ref="controllerAopHandler" order="1">
        <aop:pointcut expression="execution(* com.gary.operation.demo.UserDao.*(..))" id="allMethod"/>
        <aop:before method="actionAop" pointcut-ref="allMethod"/>
    </aop:aspect>
</aop:config> [/code]

这个代理对象是通过Spring容器拿出来的。那么因为没用使用接口 所以底层还是使用Cglib 但是输入结果却有所不同。

这是输出结果
ControllerAopHandler.actionAop()
aa
bb
[size=small][color=red]也就是说C方法被拦截了 而a,b方法没有被拦截, 单独调用A,B方法均被拦截,那么后来我分析问题大概是出在这个地方[/color][/size]

[code="java"] public void c() {
//如果是通过cglib创建的代理 那么这里的this 还是指向代理对象
//所以当this.a的时候 还是通过UserDao$$EnhancerByCGLIB$$9e419b6.a()方法
//所以被拦截了
//反之就是用Spring创建的代理对象 那么这里的this 就变成了目标对象 所以没有被拦截
//我就不明白了 这到底是咋回事呢?
System.out.println(this);
this.a();
this.b();
}[/code]

真心请教Spring高手给指点一二

  • 写回答

1条回答 默认 最新

  • jinnianshilongnian 2013-10-29 08:59
    关注

    你使用的问题
    arg3.invokeSuper(arg0, arg2); (这样强制掉父类了)
    应该是
    arg3.invoke(arg0, arg2); (而且此处不应该是arg0 而应该传入目标对象)

    你可以参考下我博客的 怎么写代理 和 aop可能遇到的自我调用问题
    [url]http://jinnianshilongnian.iteye.com/blog/1474325[/url]
    [url]http://jinnianshilongnian.iteye.com/blog/1487235[/url]

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?