2010-08-28 94 views
3

我在Spring AOP和下面的Spring配置文件嘗試我的手:BeanNotOfRequiredTypeException與Spring AOP

<?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:context="http://www.springframework.org/schema/context" 
    xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd 
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 

    <bean id="eddie" class="com.springinaction.Instrumentalist"> 
     <property name="instrument" ref="violin"></property> 
     <property name="song" value="Samarame"></property> 

    </bean> 


    <bean id="kenny" class="com.springinaction.Instrumentalist"> 
     <property name="song" value="SAMARAME "></property> 
     <property name="instrument" ref="saxopone"></property> 
    </bean> 

    <bean id="hank" class="com.springinaction.OneManBand"> 
     <property name="instruments"> 
      <props> 
       <prop key="GUITAR">STRUM STRUM STRUM</prop> 
       <prop key="CYMBAL">CRASH CRASH CRASH CRASH</prop> 
       <prop key="HARMONICA">HUM HUM HUM</prop> 
      </props> 
     </property> 
    </bean> 

    <bean id="guitar" class="com.springinaction.Guitar"> 
    </bean> 

    <bean id="violin" class="com.springinaction.Violin"> 
    </bean> 

    <bean id="tabala" class="com.springinaction.Tabala"> 
    </bean> 

    <bean id="saxopone" class="com.springinaction.Saxophone"> 
    </bean> 

    <bean id="audience" class="com.springinaction.Audience"></bean> 

    <aop:config> 

     <aop:aspect ref="audience"> 

      <aop:before pointcut="execution(* com.springinaction.Performer.perform(..))" method="takeSeats()"/> 
     </aop:aspect> 
    </aop:config> 

</beans> 

當我運行的代碼,我得到錯誤說:

異常在線程「主」 org.springframework.beans.factory.BeanNotOfRequiredTypeException: 豆命名爲‘埃迪’必須 [com.springinaction.Instrumentalist]類型, 卻被類型[$ Proxy4]實際上在 組織.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:348) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 在 org.springframework.context .support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1008) 在 com.springinaction.Main.main(Main.java:12)

如果我在評論彈簧配置文件<aop:config>元件它是完全運行狀態。 。

爲什麼它是怎麼回事?

回答

7

默認情況下,春季使用代理類適用AOP。代理類是動態創建的,以實現多個接口。你傳給它一個'處理器'對象,然後當它調用這些接口方法時調用它。您可以閱讀代理對象的Javadoc here

在初始化應用程序上下文中的所有bean之後,Spring將執行任何必要的後處理。這包括應用AOP建議。 Spring將與名稱eddie與代理對象,在你上面的例子,調用另一個對象的方法傳遞呼叫到原來的對象之前更換豆。無論何時您要求名稱爲eddie的bean,您都將獲得代理對象而不是真實對象。

我找不到上面堆棧跟蹤底部提到的Main類的源代碼,但我確實發現了代碼here的其餘大部分代碼。總之,在Main類,看來你正在做的事情一樣

Instrumentalist eddie = (Instrumentalist) appContext.getBean("eddie", Instrumentalist.class); 

Spring應用程序上下文的getBean(String, Class)方法檢查返回的bean是指定的類的,如果沒有,則拋出異常。這就是你上面例子中發生的事情。代理對象不是Instrumentalist一個實例,這就是所謂的$Proxy4自己的代理類的一個實例。 (此代理類不能是Instrumentalist一個子類,因爲所有的代理類延伸java.lang.reflect.Proxy)。

代理類將始終貫徹與他們創建的所有接口。 Spring會注意到Instrumentalist實現了Performer,所以它創建的代理類也將實現Performer。你可以用

Performer eddie = (Performer) appContext.getBean("eddie", Performer.class); 

替換上面的線,只要你只需要調用perform()方法上eddie,你的代碼應該工作。

+0

感謝Pourquoi Litytestdata爲您詳細的解答...... 好像你知道有很多關於SpringIdol競爭:) 我想我需要再次瞭解代理類... 感謝您的澄清... – javanoob 2010-08-28 15:50:48