2011-11-14 131 views
15

我有一個Spring bean,讓我們說:是否可以取消一個Spring bean?

@TransactionAttribute(TransactionAttributeType.REQUIRED) 
public class AImpl implements A { 

    public void setSomeDependency(D dependency) { 
     // This setter DOES NOT BELONG to interface A 
    } 
} 

<bean id="aImpl" class="AImpl"/> 

現在我想集成測試,但首先我需要模擬依賴D,因爲它沒有太多的東西。由於AImpl實現一個接口,幷包含事務註釋,生成的代理只與接口A兼容,因此我可以這樣做:

@Inject @Named("aImpl") 
private A a; 

但不能:

@Inject @Named("aImpl") 
private AImpl a; 

結果,我無法嘲笑我的依賴。

請注意:添加void setSomeDependency(D dependency)接口A是不是一種選擇,因爲它沒有業務含義。無論是它使用的是proxy-target-class="true",因爲它打破了一大堆其他豆類(此屬性會影響所有的豆類在上下文中)。

有沒有辦法來unproxy注入豆A,這樣我就可以將其轉換爲AImpl

+0

[將Spring的代理對象投射到實際運行時類]的可能重複(http://stackoverflow.com/questions/5976247/casting-a-springs-proxy-object-to-the-actual-runtime-class ) – skaffman

+0

@skaffman:謝謝你指出,我給春天標籤添加了這個問題FAQ –

回答

22

試試這個:

if(AopUtils.isAopProxy(a) && a instanceof Advised) { 
    Object target = ((Advised)a).getTargetSource().getTarget(); 
    AImpl ai = (AImpl)target; 
} 

獎勵:在Scala中我使用如下的等價功能非常相同的目的:

def unwrapProxy(a: AnyRef) = a match { 
    case advised: Advised if(AopUtils.isAopProxy(advised)) => 
          advised.getTargetSource.getTarget 
    case notProxy => notProxy 
} 
+8

謝謝,你真的救了我。順便說一句,我剛剛第一次訪問奧斯陸,現在我不知道你爲什麼花這麼多時間在SO(沒有冒犯意味着,但天氣不令人鼓舞):) – MaDa

+2

很高興我能幫上忙。我非常喜歡你的評論,甚至在我的個人資料頁面上引用了它;-)。 –

8

通過推出春季4.2.RC1的,現在有spring-test模塊中的專用實用程序類,可爲您處理這種情況。

的類被稱爲AopTestUtils,並且提供的方法中:

  • getTargetObject(解開僅頂層代理)
  • getUltimateTargetObject(如果它們存在解開代理的多個級別)。

查看相關的commit以及相應的issue

相關問題