Spring 动态代理分为:Dynamic proxy(针对实现了接口的类)和cglib(针对实现了无接口的类)。
CGLib与Dynamic Proxy的代理机制基本类似,Dynamic Proxy返回的动态代理类,是目标类所实现的接口的另一个实现版本,它实现了对目标类的代理,而CGLib返回的动态代理类,则是目标代理类的一个子类。
Spring缺省使用J2SE 动态代理(dynamicproxies)来作为AOP的代理。这样任何接口都可以被代理。Spring也支持使用CGLIB代理. 对于需要代理类而不是代理接口的时候CGLIB代理是很有必要的。如果一个业务对象并没有实现一个接口,默认就会使用CGLIB。
如果你的类继承了某个父类,或者实现了某个接口,因为Spring不能判断这个是jdk自带的接口,还是你自己实现的接口,所以Spring就默认使用jdk proxy了,这样子类必须要实现了一个接口,然后用这个接口来调用该类,某则就会报: $Proxy cannot be cast to xxx 之类的错误。
解决方法一、可以通过强制指定使用cglib,用下面的语句:
<bean id=”userPreferences” class=”com.foo.DefaultUserPreferences” scope=”session”>
<aop:scoped-proxy proxy-target-class=”true” />
</bean>
这样子就可以强制使用cglib,也可以直接cast该类了,当然这不是一种好习惯,实现自己的接口在测试和替换的时候毕竟比较灵活。
解决方法二、就是直接给一个接口,来处理。如:TestService(接口类)与TestServiceImpl(实现类)
那么我们在调用的时候就需要这样来处理:
// ServletContext servletContext = this.getServletContext();
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
testService= (TestService) ctx.getBean("TestService");
注意 这个是 直接 使用 TestService 这个接口来实现的,而不需要使用TestServiceImpl来转换。