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