2010-07-26 26 views
52

Cấu hình:
Xuân 2.5, Junit 4, Log4j
Vị trí tập tin log4j được quy định từ một tài sản hệ thốngĐặt Hệ thống tài sản Với cấu hình mùa xuân tập

${log.location} 

Khi chạy, sở hữu hệ thống thiết lập với - D java tùy chọn. Tất cả đều tốt.

Sự cố/Tôi cần gì:
Tại thời điểm thử nghiệm đơn vị, thuộc tính hệ thống chưa được đặt và vị trí tệp chưa được giải quyết.
Ứng dụng sử dụng Spring, muốn chỉ định cấu hình Spring thành đặt thuộc tính hệ thống.

Thông tin khác:
Yêu cầu chỉ dành cho cấu hình. Không thể giới thiệu mã Java mới hoặc các mục nhập vào IDE. Lý tưởng nhất, một trong những triển khai cấu hình thuộc tính của Spring có thể xử lý điều này - tôi chỉ không thể tìm ra sự kết hợp đúng.

Ý tưởng này là gần, nhưng cần phải thêm mã Java:
Spring SystemPropertyInitializingBean

Bất kỳ sự giúp đỡ out there? Bất kỳ ý tưởng được đánh giá cao.

+0

câu hỏi liên quan với câu trả lời thêm: http://stackoverflow.com/questions/11306951/how-to-set-environment-variable-or-system-property -in-spring-tests/41305482 – anre

Trả lời

54

Bạn có thể đạt được điều đó với sự kết hợp của hai MethodInvokingFactoryBeans

Tạo một đậu bên đó truy cập System.getProperties và đậu bên ngoài mà gọi putAll trên các tính chất mua lại bởi đậu bên trong:

<bean 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
    <property 
     name="targetObject"> 
     <!-- System.getProperties() --> 
     <bean 
      class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
      <property name="targetClass" value="java.lang.System" /> 
      <property name="targetMethod" value="getProperties" /> 
     </bean> 
    </property> 
    <property 
     name="targetMethod" 
     value="putAll" /> 
    <property 
     name="arguments"> 
     <!-- The new Properties --> 
     <util:properties> 
      <prop 
       key="my.key">myvalue</prop> 
      <prop 
       key="my.key2">myvalue2</prop> 
      <prop 
       key="my.key3">myvalue3</prop> 

     </util:properties> 
    </property> 
</bean> 

(Tất nhiên, bạn có thể sử dụng chỉ một bean và nhắm mục tiêu System.setProperties(), nhưng sau đó bạn sẽ thay thế các thuộc tính hiện tại mà không phải là một ý tưởng hay.

Dù sao, đây là phương pháp thử nghiệm nhỏ của tôi:

public static void main(final String[] args) { 

    new ClassPathXmlApplicationContext("classpath:beans.xml"); 

    System.out.println("my.key: "+System.getProperty("my.key")); 
    System.out.println("my.key2: "+System.getProperty("my.key2")); 
    System.out.println("my.key3: "+System.getProperty("my.key3")); 

    // to test that we're not overwriting existing properties 
    System.out.println("java.io.tmpdir: "+System.getProperty("java.io.tmpdir")); 
} 

Và đây là kết quả:

my.key: myvalue 
my.key2: myvalue2 
my.key3: myvalue3 
java.io.tmpdir: C:\DOKUME~1\SEANFL~1\LOKALE~1\Temp\ 
+0

Cảm ơn bạn. Những công việc này.Vấn đề còn lại: Có vẻ log4j được khởi tạo bên trong một bean khác tải trước khi các thuộc tính hệ thống mới được khởi tạo. Bây giờ tôi tìm ra cách ép buộc một lệnh khởi tạo bean. – Steve

+1

Sử dụng thuộc tính phụ thuộc của Spring. Rất cám ơn cho câu trả lời này ... nó là vàng đặc ... – HDave

+7

Mùa xuân 3 đơn giản hóa điều này bằng cách loại bỏ sự cần thiết cho MethodInvokingFactoryBean thứ 2. Bạn sử dụng Spel và dòng đối tượng đích sẽ trở thành Patrick

88

Có một yêu cầu trong các ý kiến ​​cho một ví dụ mùa xuân 3 về cách để làm điều này.

<bean id="systemPrereqs" 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
    <property name="targetObject" value="#{@systemProperties}" /> 
    <property name="targetMethod" value="putAll" /> 
    <property name="arguments"> 
     <!-- The new Properties --> 
     <util:properties> 
      <prop key="java.security.auth.login.config">/super/secret/jaas.conf</prop> 
     </util:properties> 
    </property> 
</bean> 
+0

Rất tốt, cảm ơn bạn –

+1

Tuyệt vời. Cảm ơn. – toolkit

+0

+1 Tuyệt vời. Khi tôi nghĩ có bao nhiêu mã sẽ cần phải được viết để làm điều này. Đôi khi mùa xuân là ma thuật. :-) –

10

Lô mùa xuân có thể được sử dụng để đặt thuộc tính hệ thống chính xác hơn một chút, ví dụ: để buộc JBoss đăng nhập sử dụng slf4j (với Spring JPA):

<bean id="setupJBossLoggingProperty" 
    class="org.springframework.batch.support.SystemPropertyInitializer" 
    p:keyName="org.jboss.logging.provider" p:defaultValue="slf4j"/> 

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
    depends-on="setupJBossLoggingProperty" 

Hãy nhớ thêm thuộc tính "phụ thuộc vào" để buộc thuộc tính hệ thống được đặt trước.

+0

Tôi không thể làm việc này cuối cùng. 'SystemPropertyInitializer' sử dụng' afterPropertiesSet() 'mà dường như không được gọi cho đến sau khi' 'được gọi. – Stewart

3

Đối với một cách tiếp cận nhiều hơn ngắn gọn thử:

<beans ... xmlns:p="http://www.springframework.org/schema/p" ...  
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" 
     p:targetObject="#{@systemProperties}" p:targetMethod="setProperty" 
     p:arguments="#{{'org.jboss.logging.provider','slf4j'}}"/> 
Các vấn đề liên quan