2016-11-22 34 views
3

我有兩個彈簧(4.2)的java配置中,一個基本模塊中,一個客戶端特定模塊中:如何正確過載彈簧bean配置

@Configuration 
public class BaseConfig { 

    @Bean 
    public A getA() { 
     return new A("aaa"); 
    } 

} 

@Configuration 
public class ClientConfig { 

    @Bean 
    public A getA() { 
     return new A("bbbb"); 
    } 

} 

在應用負載總是有BaseConfig.getA()所謂的,我如何ovverride基本的豆工廠配置有一些客戶特定的東西?

回答

2

就我個人而言,我絕不會在春天重寫一個bean!我看到人們花費太多時間調試與此相關的問題。出於同樣的原因,我絕不會使用@Primary。

在這種情況下,我將有三個背景

  1. 包含唯一到包含獨有的孩子上下文
  2. 包含所有共享豆摘要背景豆父上下文
  3. 語境豆語境。

這樣您將指定要加載的2個上下文。這可以通過編程方式完成,或使用配置文件。可能你需要更多的上下文,因爲你可能想讓你的一些bean在測試中有所不同。

+0

似乎是最合適的解決方案,我接受了答案,無論如何,知道爲什麼採用基本配置而不是客戶端特定配置,Spring會如何在加載配置文件時定義bean的排序和重寫? – simonC

+0

如果您有兩種配置,您可以在兩種情況下加載它們,首先是父母,然後是孩子。孩子可以看到父母的豆子,但沒有其他方式。另外 –

+0

忽視上面的評論。我會寫一個額外的答案,因爲在stackoverflow上的評論是非常蹩腳的! –

0

我不確定如何擴展bean配置類。一種解決方案是用@Primary註釋標記ClientConfig中的bean。這將導致使用Bean A的ClientConfig定義。

+0

不幸的是,這看起來沒有我的情況下 – simonC

0

如果包括配置,您可以檢查主要註解:Primary

表示一個bean應優先考慮在多個候選人有資格自動裝配單值的依賴。如果候選人中只有一個「主要」bean,它將是自動裝配的值。

+0

工作不幸的是,這看起來沒有我的情況下 – simonC

1

我認爲你應該看看@Profile註釋。你可以簡單地分割配置成不同的鹼和客戶特定一個像:

@Configuration 
@Profile("base") 
public class BaseConfig { 

    @Bean 
    public A getA() { 
     return new A("aaa"); 
    } 

} 

@Configuration 
@Profile("client") 
public class ClientConfig { 

    @Bean 
    public A getA() { 
     return new A("bbbb"); 
    } 

} 

現在通過對應用程序的主方法加入

  • @ActiveProfiles(「鹼基」)
  • 彈簧運行特定的配置文件。在application.properties profiles.active =基本條目
  • 或甚至通過個人資料名稱爲JVM PARAMS
+0

並不適用於我的情況下工作,我們需要撒尿需要一個也被定義在基本配置一些豆子,我們想只覆蓋來自base的特定bean定義。在調試過程中,我們發現第一個由spring處理的配置是客戶端特定的,之後它被base-override所覆蓋,我們只需要相反的 – simonC

+0

Ok。那麼怎麼樣:用@Profile(「config」)標記ClientConfig,離開BaseConfig而沒有配置文件。在ClientConfig中,使用@Primary標記您的bean,並使用客戶端配置文件運行應用程序。 –

0

這是回答上述評論,但由於意見已有限的格式化和大小,我會用一個答案來回答。

加載配置文件時

這取決於你通過加載多個配置的意思如何界定春豆的順序和壓倒一切的。如果你有一個spring上下文,並且有兩個帶@Configuration的類並且執行了組件掃描,那麼Spring將構建依賴樹,並且最後加載哪個上下文(bean)將定義該bean(因爲它覆蓋了第一個定義)。

如果你在父子關係中有多個Spring上下文,那麼這個子類就會看到父類bean,並且如果你使用child.getBean(type.class),它也會'覆蓋'父類。父母不能從孩子看到豆。

使用@Primary。如果你有一個Spring上下文(可以來自多個配置)定義了兩個相同類型的bean,你將不能使用context.getBean(type.class)或@AutoWired(沒有@Qualifier),因爲你有多個bean屬於同一類型。如果其中一個bean是@Primary,則可以更改此行爲。我儘量避免在自己的代碼中使用@Primary,但我可以看到它在Spring靴子自動配置系統中大量使用,所以我認爲它在框架設計方面有一些細微的用法。

這是一個小例子,請注意,如果直接加載配置類,則不需要具有@Configuration註釋。

public class ParentChildContext { 

    public static void main(String[] args) { 
     parentChildContext(); 
     twoConfigurationsSameContext(); 

    } 

    private static void twoConfigurationsSameContext() { 

     ApplicationContext ctx = new AnnotationConfigApplicationContext(Parent.class, Child.class); 
     // if you have two beans of the same type in a context they can be loaded by name 
     Object childA = ctx.getBean("childA"); 
     System.out.println("childA = " + childA); 

     Object parentA = ctx.getBean("parentA"); 
     System.out.println("parentA = " + parentA); 
     // since both configurations define A, you can't do this 
     ctx.getBean(A.class); 
    } 

    private static void parentChildContext() { 
     ApplicationContext parentCtx = new AnnotationConfigApplicationContext(Parent.class); 

     A parentA = parentCtx.getBean(A.class); 
     System.out.println("parent = " + parentA); 

     AnnotationConfigApplicationContext childCtx = new AnnotationConfigApplicationContext(); 
     childCtx.register(Child.class); 
     childCtx.setParent(parentCtx); 
     childCtx.refresh(); 

     A childA = childCtx.getBean(A.class); 
     System.out.println("child = " + childA); 
    } 


    public static class Parent { 
     @Bean 
     //@Primary // if you enable @Primary parent bean will override child unless the context is hierarchical 
     public A parentA() { 
      return new A("parent"); 
     } 
    } 

    public static class Child { 
     @Bean 
     public A childA() { 
      return new A("child"); 
     } 
    } 


    public static class A { 
     private final String s; 

     public A(String s) { 
      this.s = s; 
     } 
     @Override 
     public String toString() { 
      return "A{s='" + s + "'}"; 
     } 
    } 
}