Post

Spring Properties

Hướng dẫn này sẽ chỉ ra cách thiết lập và sử dụng các Property trong Spring thông qua cấu hình Java và @PropertySource hoặc qua XML<property-placeholder>.

1. Register một Properties File qua Java Annotation

Spring 3.1 cũng đã giới thiệu chú thích @PropertySource mới như một cơ chế thuận tiện để thêm các property nguồn vào môi trường.

Chú thích này sẽ được sử dụng cùng với cấu hình dựa trên Java và chú thích @Configuration:

1
2
3
4
5
@Configuration
@PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
    //...
}

Một cách rất hữu ích khác để đăng ký properties file mới là sử dụng placeholder, cho phép chúng ta chọn dynamically file phù hợp trong thời gian chạy:

1
2
3
@PropertySource({ 
  "classpath:persistence-${envTarget:mysql}.properties"
})

Xác định nhiều vị trí Property

Chú thích @PropertySource có thể lặp lại theo các quy ước của Java 8. Do đó, nếu đang sử dụng Java 8 trở lên, chúng ta có thể sử dụng chú thích này để xác định nhiều vị trí Property:

1
2
3
4
5
@PropertySource("classpath:foo.properties")
@PropertySource("classpath:bar.properties")
public class PropertiesWithJavaConfig {
    //...
}

Tất nhiên, chúng ta cũng có thể sử dụng chú thích @PropertySources và chỉ định một mảng của @PropertySource. Nó hoạt động trong bất kỳ phiên bản Java nào được hỗ trợ, không chỉ trong Java 8 trở lên:

1
2
3
4
5
6
7
@PropertySources({
    @PropertySource("classpath:foo.properties"),
    @PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
    // code something
}

Trong cả hai trường hợp, ta cần lưu ý rằng trong trường hợp có xung đột tên property thì việc đọc source cuối cùng sẽ được ưu tiên.

2. Register một Properties File trong XML

Trong XML, Spring có thể truy cập các file property thông qua phần tử

1
2
<context:property-placeholder>:
<context:property-placeholder location="classpath:foo.properties" />

File foo.properties nên được đặt bên trong /src/main/resources để nó có sẵn trên classpath khi chạy. Trong trường hợp có nhiều phần tử <property-placeholder> trong ngữ cảnh Spring, có một số phương pháp hay nhất được đề xuất:

  • Thuộc tính order cần được chỉ định để sửa thứ tự mà Spring xử lý các property này.
  • Tất cả các property placeholder trừ đi cái cuối cùng (thứ tự cao nhất) phải có ignore-unresolvable = ”true” để cho phép cơ chế phân giải chuyển cho những ngữ cảnh khác mà không đưa ra ngoại lệ.

Register nhiều Properties Files trong XML

Trong phần trước, chúng ta đã biết cách xác định nhiều file property bằng cách sử dụng chú thích từ Java 8 trở lên. Tương tự, chúng ta có thể xác định nhiều file property bằng cách sử dụng cấu hình XML:

1
<context:property-placeholder location="classpath:foo.properties, classpath:bar.properties"/>

Và như trước đây, trong trường hợp có xung đột tên thuộc tính, việc đọc source cuối cùng sẽ được ưu tiên.

Sử dụng/Inject Properties

Inject một property với chú thích @Value rất đơn giản:

1
2
@Value( "${jdbc.url}" )
private String jdbcUrl;

Chúng ta cũng có thể chỉ định một giá trị mặc định cho property:

1
2
@Value( "${jdbc.url:aDefaultUrl}" )
private String jdbcUrl;

Và làm điều tương tự bằng cách sử dụng cấu hình XML:

1
2
3
<bean id="dataSource">
    <property name="url" value="${jdbc.url}" />
</bean>

Cả PropertyPlaceholderConfigurer cũ và PropertySourcesPlaceholderConfigurer mới được thêm vào Spring 3.1 đều giải quyết các placeholder ${…} trong các giá trị property định nghĩa bean và chú thích @Value. Cuối cùng, chúng ta có thể lấy giá trị của một thuộc tính bằng Environment API:

1
2
3
4
@Autowired
private Environment env;
...
dataSource.setUrl(env.getProperty("jdbc.url"));

Một lưu ý rất quan trọng ở đây là việc sử dụng <property-placeholder> sẽ không hiển thị các thuộc tính cho Spring Environment. Điều này có nghĩa là việc truy xuất giá trị như thế này sẽ không hoạt động - nó sẽ trả về null:

1
env.getProperty("key.something")

3. Cấu hình sử dụng Bean - PropertyPlaceholderConfigurer

Cấu hình sử dụng Bean thô trong Spring 3.0 – PropertyPlaceholderConfigurer

Bên cạnh các phương pháp thuận tiện để lấy property từ Spring – chú thích và XML namespace - property configuration cũng có thể được định nghĩa và đăng ký theo cách thủ công.

Làm việc với PropertyPlaceholderConfigurer cho phép chúng ta toàn quyền kiểm soát cấu hình, với nhược điểm là dài dòng hơn và hầu hết thời gian là không cần thiết. Hãy xem cách chúng ta có thể xác định bean này bằng cách sử dụng cấu hình Java:

1
2
3
4
5
6
7
8
9
10
@Bean
public static PropertyPlaceholderConfigurer properties() {
    PropertyPlaceholderConfigurer ppc
      = new PropertyPlaceholderConfigurer();
    Resource[] resources = new ClassPathResource[]
      { new ClassPathResource( "foo.properties" ) };
    ppc.setLocations( resources );
    ppc.setIgnoreUnresolvablePlaceholders( true );
    return ppc;
}

Và sử dụng cấu hình XML:

1
2
3
4
5
6
7
8
9
<bean 
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:foo.properties</value>
        </list>
    </property>
    <property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>

Cấu hình sử dụng Bean thô trong Spring 3.1 – PropertySourcesPlaceholderConfigurer

Tương tự, trong Spring 3.1 - PropertySourcesPlaceholderConfigurer mới cũng có thể được cấu hình theo cách thủ công như sau:

1
2
3
4
5
6
7
8
9
10
@Bean
public static PropertySourcesPlaceholderConfigurer properties(){
    PropertySourcesPlaceholderConfigurer pspc
      = new PropertySourcesPlaceholderConfigurer();
    Resource[] resources = new ClassPathResource[ ]
      { new ClassPathResource( "foo.properties" ) };
    pspc.setLocations( resources );
    pspc.setIgnoreUnresolvablePlaceholders( true );
    return pspc;
}

Và cấu hình XML tương ứng:

1
2
3
4
5
6
7
8
9
<bean
  class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:foo.properties</value>
        </list>
    </property>
    <property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>

Properties trong Parent-Child Contexts

Câu hỏi này lặp đi lặp lại: Điều gì sẽ xảy ra khi ứng dụng web của chúng ta có Parent-Child Contexts? Parent context có thể có một số chức năng cốt lõi chung, các bean và sau đó là một (hoặc nhiều) child contexts có thể chứa các bean dành riêng cho servlet.

Trong trường hợp đó, cách tốt nhất để xác định các file property và đưa chúng vào các ngữ cảnh này là gì? Và làm thế nào để lấy các property này từ Spring một cách tốt nhất?

Chúng ta sẽ đưa ra một phân tích đơn giản.

  • Nếu file property được định nghĩa bằng XML với <property-placeholder>
    • Nếu file được định nghĩa trong Parent context:
      • @Value hoạt động trong Child context: KHÔNG
      • @Value hoạt động trong Parent context: CÓ
    • Nếu file được định nghĩa trong Child context:
      • @Value hoạt động trong Child context:: CÓ
      • @Value hoạt động trong Parent context:KHÔNG

Cuối cùng, như chúng ta đã thảo luận trước đây, <property-placeholder> không hiển thị các property với environment. Vì vậy: environment.getProperty hoạt động trong một trong hai ngữ cảnh: KHÔNG

  • Nếu file property được định nghĩa với @PropertySource
    • Nếu file được định nghĩa trong Parent context:
      • @Value hoạt động trong Child context: YES
      • @Value hoạt động trong Parent context: YES
      • environment.getProperty trong Child context: YES
      • environment.getProperty trong Parent context: YES
    • Nếu file được định nghĩa trong Child context:
      • @Value hoạt động trong Child context: YES
      • @Value hoạt động trong Parent context: NO
      • environment.getProperty trong Child context: YES
      • environment.getProperty trong Parent context: NO

Bài viết này đưa ra một số ví dụ về cách làm việc với các PropertyProperty File trong Spring. Như mọi khi, đây chỉ là các kiến thức nền cơ bản như khá rộng và khó – vì nó đã nằm ở mức độ của Framework. Bạn và tôi có lẽ cần thời gian để hiểu và thích nghi để làm quen và có thể vận dụng được vào thực tế.

Bài viết mang tính chất “ghi chú, lưu trữ, chia sẻ và phi lợi nhuận”.
Nếu bạn thấy hữu ích, đừng quên chia sẻ với bạn bè và đồng nghiệp của mình nhé!

Happy coding! 😎 👍🏻 🚀 🔥

Đọc thêm:

This post is licensed under CC BY 4.0 by the author.