在測試Spring使用xml實現aop時出現以下錯誤:Exception in thread "main" org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'performance' must be of type [Concert.PerformanceImpl], but was actually of type [com.sun.proxy.$Proxy3]
具體代碼如下:
Audience類:
package Concert; import org.aspectj.lang.annotation.*; //@Aspect public class Audience { //@Pointcut("execution(* Concert.Performance.perform(..))") public void perform(){} //@Before("perform()") public void performBefore(){ System.out.println("表演即將開始,請各位入座"); } //@AfterReturning("perform()") public void performce(){ System.out.println("請盡情開始你的表演。"); } //@After("perform()") public void performAfter(){ System.out.println("表演結束,請離場"); } @AfterThrowing("execution(* Concert.Performance.performFailed())") public void Over(){ System.out.println("表演失敗,一切都完了"); } }
Performance接口:
package Concert; public interface Performance { public void perform(); public void performFailed() throws Exception; }
PerformanceImpl實現類:
package Concert; //@Component public class PerformanceImpl implements Performance { public void perform(){ System.out.println("蹦擦擦,蹦擦擦..."); } public void performFailed() throws Exception { throw new Exception(); } }
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"> <!--<aop:aspectj-autoproxy proxy-target-class="true"/>--> <bean id="performance" class="Concert.PerformanceImpl"/> <bean id="audience" class="Concert.Audience" /> <aop:config> <aop:aspect ref="audience"> <aop:pointcut id="perform" expression="execution(* Concert.Performance.perform(..))"/> <aop:before method="performBefore" pointcut-ref="perform"/> <aop:before method="performBefore" pointcut-ref="perform"/> <aop:after method="performAfter" pointcut-ref="perform"/> <aop:after-returning method="performce" pointcut-ref="perform"/> <aop:after-throwing method="Over" pointcut="execution(* Concert.Performance.perform(..))"/> </aop:aspect> </aop:config> </beans>
測試內容:
import Concert.Audience; import Concert.PerformanceImpl; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { /*AnnotationConfigApplicationContext apx = new AnnotationConfigApplicationContext(); apx.register(Config.class); apx.refresh();*/ ClassPathXmlApplicationContext apx = new ClassPathXmlApplicationContext("classpath:Config/AspectsConfig.xml"); Audience audience = apx.getBean(Audience.class); audience.performAfter(); PerformanceImpl performance = apx.getBean("performance",PerformanceImpl.class); performance.perform(); try{ performance.performFailed(); }catch (Exception e){ // e.printStackTrace(); } apx.close(); } }
原因:Spring 有兩種代理動態代理模式,一種是基於接口的JDK動態地理,一種是基於類的CGLibs動態代理,Spring默認是使用JDK動態代理的,所以要么使用JDK動態代理,要么使用CGLibs實現動態代理。
解決方法:
1、使用基於接口的JDK動態代理:將測試代碼中的
PerformanceImpl performance = apx.getBean("performance",PerformanceImpl.class);
改為
Performance performance = apx.getBean("performance", Performance.class);
2、使用基於類的CGLIBS動態代理:在配置文件中添加
<aop:aspectj-autoproxy proxy-target-class="true"/>強制使用類代理模式。
