Spring报错:java.lang.ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to *

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




猜你喜欢

转载自blog.csdn.net/u011159417/article/details/77925336