2016-12-27 70 views
0

我在我的Spring應用程序類似這樣的語法:春:實例化一個類依賴於字符串參數

public OAuthClient getOAuthClient(String clientType, ClientConfig config){ 
    switch (clientType) { 
     case "google": 
      return new GoogleOAuthClient(config); 
     case "facebook": 
      return new FacebookOauthClient(config); 
     case "linkedIn": 
      return new LinkedInOauthClient(config); 
     //... more clients 
     default: 
      return new BasicOauthClient(config); 
    } 
} 

如何管理這樣的實例與Spring XML的配置?

+0

方法中沒有返回類型 –

+0

代碼中缺少返回類型。 – mm759

+0

謝謝,更正 –

回答

2

您可以自動裝入實現或擴展OAuthClient的類的列表。例如,如果您有一個「getName()」方法,您將能夠選擇好的一個:

@Autowired 
List<OAuthClient> clients; 
public OAuthClient getOAuthClient(String clientType, ClientConfig config){ 
    foreach (OAuthClient client : clients) { 
     if (client.getName().equals(clientType)) { 
      return client; 
     } 
    } 
    // Return null or throw exception 
    return null; 
} 
+0

好的,但這需要有一個實例列表,我需要使用構造函數參數按需實例化。 –

+0

所以你不想用spring來實例化嗎? –

+0

您可以使用反射來創建實例:您可以爲類創建一個Map assiociating名稱,然後使用反射調用。 –

2

有點兒不清楚你打算做什麼。但是,如果您想將OAuthClient作爲託管bean及其基於某些條件的創建,則可以使用工廠。首先,創建工廠類:

public class OAuthClientFactory{ 
    public OAuthClient createOAuthClient(String clientType, ClientConfig config){ 
     //Conditional creation logic... 
    } 
} 

現在XML的配置聲明豆:

<bean id="authClientFactory" class="com.somepackage.OAuthClientFactory"/> 
<bean id="clientConfig" class="com.somepackage.ClientConfig"/> 

<bean id="authClient" class="com.somepackage.OAuthClient " factory-bean="authClientFactory" 
    factory-method="createOAuthClient"> 
    <constructor-arg value="google"/> 
    <constructor-arg ref="clientConfig"/> 
</bean> 

ClinetConfig也必須託管bean的把它作爲參數傳入工廠方法。爲了讓示例更簡單,我只是將它聲明爲bean,但在實際代碼中,您應該決定如何創建它。


根據您最後的評論,您需要按需實例化客戶端實例。你想避免任何有條件的操作,並通過「春天的方式」。然後,你應該註冊所有類型的客戶端爲具有相應名稱的bean。

如果您需要在每次新的客戶端請求時創建新實例,你應該把它聲明爲prototype豆:

... 
<bean id="googleClient" class="com.somepackage.GoogleOAuthClient" scope="prototype"/> 
<bean id="facebookClient" class="com.somepackage.FacebookOauthClient" scope="prototype"/> 
... 

或者,如果你只需要一個(單)每個請求的客戶端的情況下其聲明作爲lazy-init

... 
<bean id="googleClient" class="com.somepackage.GoogleOAuthClient" lazy-init="true"/> 
<bean id="facebookClient" class="com.somepackage.FacebookOauthClient" lazy-init="true"/> 
... 

在這兩種情況下,客戶端的實例將僅由需求創建。現在,您可以通過從ApplicationContext請求獲取客戶端的實例:

@Service 
public class SomeService{ 

    @Autowired 
    private ApplicationContext context; 

    public void SomeMethod(){ 
     ClientConfig config = ... //obtain client config 
     GoogleOAuthClient client = (GoogleOAuthClient)context.getBean("googleClient", config); 
    } 
} 

或者,如果你不使用基於註解注射,然後實現ApplicationContextAware接口獲取ApplicationContext

+0

問題是如何擺脫這個醜陋的選擇,這將在這裏以及'OAuthClientFactory#createOAuthClient' –