2012-11-22 59 views
1

有什麼事情,可以實現的下方相當於:春:導入模塊指定的環境

<import resource="a.xml"> 
    <prop name="key" value="a"/> 
</import> 

<import resource="a.xml"> 
    <prop name="key" value="b"/> 
</import> 

使得在種源定義的豆會看到兩個不同的值屬性鍵?其意圖是,這將被用來命名的進口豆,使得資源A.XML會出現:

<bean id="${key}"/> 

,因此應用程序將有一個名爲ab現在可以用同一個定義兩個bean但作爲不同的實例。我瞭解原型範圍;它並不是出於這個原因,將會有許多對象被創造出來,而這些對象並不是真正的原型。目前,我只是簡單地複製a.xml,創建b.xml並使用sed命令的等效命名將所有bean重命名。我覺得必須有更好的方法。

回答

1

我想PropertyPlaceholderConfigurers每個容器的基礎上工作,所以你不能用xml導入實現這一點。

重新The application would have two beans named a and b now available with the same definition but as distinct instances

我想你應該考慮(ClassPathXmlApplicationContext的舉例)手動創建額外的應用環境中,使用當前的應用程序上下文作爲父應用程序上下文。 因此,您的many objects created with interdependencies套件將分別位於其自己的容器中。

但是,在這種情況下,您將無法引用b-來自a -container。

更新,您可以手動註冊BeanDefinitionRegistryPostProcessor專門豆後處理的bean定義(添加新的),但這種方法也似乎並不容易。

OK,這是我的粗略嘗試手動導入XML文件:

免責聲明:我很差勁的Java IO程序員居然如此仔細檢查資源相關的代碼:-)

public class CustomXmlImporter implements BeanDefinitionRegistryPostProcessor { 

    @Override 
    public void postProcessBeanFactory(
      ConfigurableListableBeanFactory beanFactory) throws BeansException { 
    } 

    private Map<String, String> properties; 

    public void setProperties(Map<String, String> properties) { 
     this.properties = properties; 
    } 

    public Map<String, String> getProperties() { 
     return properties; 
    } 

    private void readXml(XmlBeanDefinitionReader reader) { 
     InputStream inputStream; 
     try { 
      inputStream = new ClassPathResource(this.classpathXmlLocation).getInputStream(); 
     } catch (IOException e1) { 
      throw new AssertionError(); 
     } 
     try { 

      Scanner sc = new Scanner(inputStream); 
      try { 
       sc.useDelimiter("\\A"); 
       if (!sc.hasNext()) 
        throw new AssertionError(); 
       String entireXml = sc.next(); 

       PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", 
         "}", null, false); 
       Properties props = new Properties(); 
       props.putAll(this.properties); 
       String newXml = helper.replacePlaceholders(entireXml, props); 
       reader.loadBeanDefinitions(new ByteArrayResource(newXml.getBytes())); 

      } finally { 
       sc.close(); 
      } 

     } finally { 
      try { 
       inputStream.close(); 
      } catch (IOException e) { 
       throw new AssertionError(); 
      } 
     } 
    } 

    private String classpathXmlLocation; 

    public void setClassPathXmlLocation(String classpathXmlLocation) { 
     this.classpathXmlLocation = classpathXmlLocation; 
    } 

    public String getClassPathXmlLocation() { 
     return this.classpathXmlLocation; 
    } 

    @Override 
    public void postProcessBeanDefinitionRegistry(
      BeanDefinitionRegistry registry) throws BeansException { 
     XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry); 
     readXml(reader); 
    } 
} 

XML配置:

<bean class="CustomXmlImporter"> 
    <property name="classPathXmlLocation" value="a.xml" /> 
    <property name="properties"> 
     <map> 
      <entry key="key" value="a" /> 
     </map> 
    </property> 
</bean> 
<bean class="CustomXmlImporter"> 
    <property name="classPathXmlLocation" value="a.xml" /> 
    <property name="properties"> 
     <map> 
      <entry key="key" value="b" /> 
     </map> 
    </property> 
</bean> 

此代碼從classpath加載資源。在做這樣的事情之前,我會三思而後行,無論如何,你可以以此爲出發點。

+0

嗯,聽起來像這樣可能會有用,但我希望能夠從Spring XML本身做到這一點(這是一個無聊的故事,但基本上這就是我們目前設置的目的 - 而不是它不能改變它只會花費比我想要做的更長的時間)。 – cyborg

+0

@cyborg我不認爲會有一個可靠的方法來做到這一點,因爲如果你忘了給它們提供唯一的ID,那麼一些bean將被定義兩次,同樣的事情是關於內在的相互依賴關係。有一些特定的XML工具,比如',但它們只是編譯時檢查,bean解析幾乎完全由容器(它的bean定義和層次結構)來確定,而XML配置是次要的,只是一個bean定義的來源。 –

+0

這就是我所能找到的東西。但正如我所說,目前這種設置方式不利於您的解決方案。但是我認爲我可以在現有的XML上下文中創建自己的Bean,該上下文將加載具有適當上下文的指定XML文件,然後根據我的方案進行重命名(假定需要對此bean進行修改)。 – cyborg