2012-10-23 17 views
4

工作,我有一個單身的Spring bean(和它必須留單),它需要其他bean的新的事例(讓我們把它叫做X)的每一個特定的方法執行時間。如何獲得一個工廠+ AOP在Spring

到目前爲止,我看着下面的方法:

  • 使用新的只是創建X。這工作了一段時間,但現在我們需要X的Spring AOP特性,所以這不再起作用,因爲結果實例不是Spring管理的。

  • 我認爲一個FactoryBean作爲依賴,但我只會從FactoryBean的,這不符合我的第一個實例獲得一個X的實例。

  • 目前的計劃是手動查找在Spring上下文X,並與一個原型依賴性有聲明它。這應該有效,但我認爲這真的很難看。

=>如何注入我的豆工廠,這樣我可以調用它的工廠方法,任何時候我認爲合適並得到一個Spring管理的實例出來。

回答

12

像這樣的情況下選擇的手段被稱爲lookup method injection。簡而言之,它使用調用bean方法的方法來創建一個新的bean實例。

abstract class MyClient implements Client { 

    void businessMethod(…) { 

    Dependency dependency = getDependencyInstance(); 
    … 
    } 

    abstract Dependency getDependencyInstance(); 
} 

現在繼續和配置的依賴原型bean定義:

<bean id="dependency" class="….DependencyImpl" scope="prototype" /> 

除了你會用一個抽象方法,將最終提供的依賴實例創建一個類開始作爲使用lookup-method元素的客戶總是爲每個方法調用的依賴性的一個新的實例:

<bean class="….MyClient"> 
    <lookup-method name="getDependencyInstance" bean="dependency" /> 
</bean> 

這將導致爲MyClient創建CGLib代理,getDependencyInstance(…)的方法聲明由TargetSource支持,並參考BeanFactory以及要查找的bean的名稱。在每個方法調用中,bean查找都會被觸發,並返回原型配置bean的新實例。

+0

我在我自己的代碼中使用這種技術;它工作得很好。唯一不利的一面是包含它的類是抽象的,這減少了您的IDE可能提供的用於填充其他接口中聲明的方法的支持量。 –

2

我沒有看到工廠bean的問題,我會做它像這樣:

import org.springframework.beans.factory.FactoryBean; 
import org.springframework.stereotype.Component; 

@Component 
public class X { 
    public static class XFactory implements FactoryBean<X> { 

     @Override 
     public X getObject() throws Exception { 
      return new X(); 
     } 

     @Override 
     public Class<?> getObjectType() { 
      return X.class; 
     } 

     @Override 
     public boolean isSingleton() { 
      return false; 
     }  
    } 
} 

,並注入該工廠bean。

否則,您可以範圍的X豆與

@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS, value=ConfigurableBeanFactory.SCOPE_PROTOTYPE) 

你必須讓春天創建一個代理,它總是返回一個新的實例,以你的單身使用非默認的代理模式。

如果你在XML配置要比做像這樣:

<bean id="x" class="X" scope="prototype"> 
<aop:scoped-proxy> 
</bean> 

有樂趣。

編輯:

當你通過註釋@Component貴廠(我上面添加的話),在#isSingleton返回false,並確保你不回你X的兩倍,你可以注入工廠bean與@Autowired到你的單身人士。

否則我剛剛檢查

import org.springframework.context.annotation.Scope; 
import org.springframework.context.annotation.ScopedProxyMode; 
import org.springframework.stereotype.Component; 

@Component 
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS) 
public class X { 
} 

它按預期工作。

編輯2:

如果你不想注入工廠bean,但只是想你注入可以原型範圍貴廠的依賴(@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS,值=「原型」 )),但每次涉及X時都會創建一個新工廠,這可能不是您想要的。

如果你不想讓工廠本身注入我會跟奧利弗查找方法去。

+0

但是我不會在我的依賴類A中獲得單個X實例嗎?我的理解是,如果我注入一個FactoryBean,我只能得到FactoryBean的一個實例而不是FactoryBean本身? –

+0

是的,你是正確的,如果你從你的應用程序上下文中詢問另一個實例,你只會得到一個不同的bean實例,所以建立一個工廠,讓它實現ApplicationContextAware(我認爲它叫做)並給它一個getX()方法調用applicationcontext.getbean(X.class),並將X聲明爲原型。或者沿着這些線 –

+0

Jens:你可以像其他任何bean一樣注入一個工廠bean並直接調用它的方法。 –