<spring-aop> BeanNotOfRequiredTypeException 切面异常

[b]1. 问题描述[/b]
往工程里添加切面,定义了<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]


[b]2. 问题分析[/b]
这个异常一般是代理问题,根据异常中的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的讲解([url]http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-proxying[/url]):
[quote]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.[/quote]
所以就强制所有代理都使用了cglib。cglib代理后生成的类型是类,不能转成接口,这里期待的类型也是类,但新增的切面仍然使用了<aop:aspectj-autoproxy/>的配置,jdk代理。这个代理类类型与期待的接口的实现类类型不符合,造成异常。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值