照书上步骤使用BeanNameAutoProxyCreator为项目添加了spring事务管理机制,可是在java代码中使用 
StudentDAO stdao = (StudentDAO)ctx.getBean("StudentDAO"); 
Student st = new Student("张三"); 
stdao.save(st); 
报错java.lang.ClassCastException: $Proxy0 cannot be cast to... 网上说需要将ctx.getBean()方法的返回值用接口类接收,改为 
IStudentDAO stdao = (IStudentDAO)ctx.getBean("StudentDAO"); 
Student st = new Student("张三"); 
stdao.save(st); 
其中IStudentDAO是接口类,StudentDAO是它的实现类.我不明白的是,这里为什么申明一个接口类可以直接使用实现类定义的方法呢?ctx.getBean()的返回值明明被强制转换成了IStudentDAO啊,是不是因为Spring管理机制在捣鬼呢? 
希望有高手能详细给我解释解释这样用接口类的理由,为什么放着实现类不用,直接使用接口类的方法,如果是Spring事务管理在捣鬼,希望也能解释一下为什么Spring事务管理要这么设计。

解决方案 »

  1.   

    个人理解是这样的。Spring AOP它默认是采用JDK的动态代理实现的,首先会去判断具体实现类是否实现了接口,如果实现了接口就执行AOP。当然也可以不去实现接口,那么需要借助CGLIB去实现它的AOP,这种方法需要加入CGLIB的包,同时需要修改Spring配置文件。
    Spring的这种设计方式应该也是一种面向接口的编程,推荐使用接口,使用接口的好处就是代码整理业务实现不会依赖到具体类的实现,层与层之间的耦合度,依赖度降低了,从而使修改代码更方面,分层更清晰。仅供参考。
      

  2.   


    aop还没学习.
    不过向你说的我感觉还是有点道理的.
    up
      

  3.   

    楼上的完全正确 
    代理据说有5种,常用的有jdk的动态代理和CGLIB的代理,spring的aop实现是基于代理实现的,CGLIB的代理是生成目标类的子类,jdk的动态代理是生成接口的实现类,所以产生的实现类是不能转换成你的实现类的,因为他们是平级的啊,都是实现的统一的接口,所以只能转换成接口的类型,$Proxy0 cannot be cast to... 就是这个意思,也就是说,如果你配置了CGLIB(加入jar)又实现了接口,那么spring会优先使用jdk的动态代理,除非你强制让它使用CGLIB
      

  4.   

    lz大哥,您既然是用到了Spring,那么Spring最基本的就是在他的测试类中是很少见到NEW的,如果要测试某个方法,建议您最好用ApplicationContext来进行测试,如ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");

    测试类 user=(测试类)ac.getBean("");
    然后调用测试类的方法就行,当然还需要在spring中把你的测试类需要加一个bean 的ID就行了