Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to com.myspring.chapter01.BraveKnight at com.myspring.test.Main.main(Main.java:12)
在使用Spring的aop切面时,在xml配置文件中配置了如下代码:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="knight" class="com.myspring.chapter01.BraveKnight"> <constructor-arg ref="quest" /> </bean> <bean id="quest" class="com.myspring.chapter01.SlayDragonQuest"> <constructor-arg value="#{T(System).out}" /> </bean> <bean id="minstrel" class="com.myspring.chapter01.Minstrel"> <constructor-arg value="#{T(System).out}" /> </bean> <aop:config> <aop:aspect ref="minstrel"> <aop:pointcut id="embark" expression="execution(* *.embarkOnQuest(..))"/> <aop:before pointcut-ref="embark" method="singBeforeQuest"/> <aop:after pointcut-ref="embark" method="singAfterQuest"/> </aop:aspect> </aop:config> </beans>
对应的各个java类代码分别如下
BraveKnight.java代码如下:
package com.myspring.chapter01; import com.myspring.chapter01.interfaces.Knight; import com.myspring.chapter01.interfaces.Quest; public class BraveKnight implements Knight { private Quest quest ; public BraveKnight(Quest quest) { this.quest = quest ; } @Override public void embarkOnQuest() { quest.embark() ; } }
Knight接口如下:
package com.myspring.chapter01.interfaces; public interface Knight { void embarkOnQuest() ; }
SlayDragonQuest.java代码如下:
package com.myspring.chapter01; import java.io.PrintStream; import com.myspring.chapter01.interfaces.Quest; public class SlayDragonQuest implements Quest { private PrintStream stream ; public SlayDragonQuest(PrintStream stream){ this.stream = stream ; } @Override public void embark() { stream.println("Embarking on quest to slay the dragon!") ; } }
Quest接口代码如下:
package com.myspring.chapter01.interfaces; public interface Quest { void embark() ; }
Minstrel.java代码如下:
package com.myspring.chapter01; import java.io.PrintStream; public class Minstrel { private PrintStream stream; public Minstrel(PrintStream stream) { this.stream = stream; } public void singBeforeQuest() { stream.println("Fa la la, the knight is so brave!"); } public void singAfterQuest() { stream.println("Tee hee hee, the brave knight " + "did embark on a quest!"); } }
测试类代码Main如下:
package com.myspring.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.myspring.chapter01.BraveKnight; public class Main { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("minstrel.xml") ; BraveKnight h = (BraveKnight) ac.getBean("knight") ; h.embarkOnQuest() ; } }
运行后,控制台打印错误,错误信息如下:
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to com.myspring.chapter01.BraveKnight at com.myspring.test.Main.main(Main.java:12)
在网上查询后有人说是应为代理的问题,增加如下代码即可解决:
proxy-target-class="true"
增加后xml配置文件如下:
<aop:config proxy-target-class="true">
<aop:aspect ref="minstrel">
<aop:pointcut id="embark"
expression="execution(* *.embarkOnQuest(..))"/>
<aop:before pointcut-ref="embark"
method="singBeforeQuest"/>
<aop:after pointcut-ref="embark"
method="singAfterQuest"/>
</aop:aspect>
</aop:config>
再次运行确实没有问题了,
原因分析如下:
动态代理分为两种:
1、针对接口的动态代理;
2、针对普通类的动态代理。
java中的jdk动态代理是针对接口的动态代理,而cglib是针对普通类的动态代理,
javaEE的依赖包中有jdk动态代理包,Spring的jar包中也包含了cglib相关jar包,因此即可以对接口也可以对普通类进行动态代理。
在<aop:config proxy-target-class="true">
</aop:config>加上红色字体的一段即可
其中proxy-target-class="true/false"属性,决定是基于接口的还是基于类的代理被创建。
如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。
如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。
即使你未声明 proxy-target-class="true" ,但运行类没有继承接口,spring也会自动使用CGLIB代理。
高版本spring自动根据运行类选择 JDK 或 CGLIB 代理
文章参考:http://www.cnblogs.com/applemy/p/6704161.html