BeanNotOfRequiredTypeException 切面异常

1. 问题描述
往工程里添加切面,定义了<aop:aspectj-autoproxy/>,切的是实现了接口的类,这样的话使用jdk代理应该没啥问题。但是启动时报错:
BeanNotOfRequiredTypeException
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'x' must be of type [y], but was actually of type [com.sun.proxy.$Proxy23]


2. 问题分析
这个异常一般是代理问题,根据异常中的com.sun.proxy.$Proxy23可以判断。但是奇怪的是为什么会类型不对,动态代理接口应该没有问题,于是查找工程中其他地方是否也使用了代理相关的功能。
1)因为有好几个spring配置文件,就搜索有没有其他<tx:annotation-driven/>, <aop:aspectj-autoproxy/> 或<aop:config/>,如果有的话就看下是否有proxy-target-class="true"的配置  ---结果没有
2)查看是否有注解@Transactional的使用 -- 找到
发现@Transactional是加在**DAO方法上的,但是这个DAO没有实现接口,而是继承的父DAO类。问题明确了,动态代理只能代理实现了接口且是接口里定义的方法,否则就会强制使用cglib代理。即使DAO类实现的是接口,但@Transactional加在了不是接口里定义的方法上,仍然会走cglib代理,本人遇到的就是这个问题。

根据spring的讲解( http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-proxying):
引用
Multiple <aop:config/> sections are collapsed into a single unified auto-proxy creator at runtime, which applies the strongest proxy settings that any of the <aop:config/> sections (typically from different XML bean definition files) specified. This also applies to the <tx:annotation-driven/> and <aop:aspectj-autoproxy/> elements.
To be clear: using ' proxy-target-class="true"' on <tx:annotation-driven/>, <aop:aspectj-autoproxy/> or <aop:config/> elements will force the use of CGLIB proxies for all three of them.
So be careful when defining these tags in multiple xml configuration files.

所以就强制所有代理都使用了cglib。cglib代理后生成的类型是类,不能转成接口,这里期待的类型也是类,但新增的切面仍然使用了<aop:aspectj-autoproxy/>的配置,jdk代理。这个代理类类型与期待的接口的实现类类型不符合,造成异常。

3. 解决办法
显式加上proxy-target-class="true",配置成<aop:aspectj-autoproxy proxy-target-class="true"/>

可以参考:
官方: https://jira.spring.io/browse/SPR-11859
http://jinnianshilongnian.iteye.com/blog/1901694
http://jinnianshilongnian.iteye.com/blog/1894465

补充:
spring @Transactional代理注意事项:
@Transactional 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在 同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。
更多事项参考: http://blog.sina.com.cn/s/blog_667ac0360102ebem.html

你可能感兴趣的:(切面异常)