Đừng lạm dụng các lĩnh vực riêng tư nhận / thiết lập bởi sự phản ánh
Sử dụng sự phản chiếu như được thực hiện trong một số câu trả lời ở đây là điều mà chúng ta có thể tránh.
Nó mang lại một giá trị nhỏ ở đây trong khi nó thể hiện nhiều nhược điểm:
- chúng tôi chỉ phát hiện các sự cố phản ánh trong thời gian chạy (ví dụ: các trường không còn tồn tại nữa)
- Chúng tôi muốn đóng gói nhưng không phải là một lớp mờ che giấu các phụ thuộc cần nhìn thấy và làm cho lớp này mờ hơn và ít kiểm tra hơn.
- nó khuyến khích thiết kế xấu. Hôm nay bạn tuyên bố a
@Value String field
. Ngày mai bạn có thể tuyên bố 5
hoặc 10
trong số họ trong lớp đó và bạn thậm chí có thể không nhận thức được rằng bạn giảm thiết kế của lớp. Với cách tiếp cận rõ ràng hơn để đặt các trường này (chẳng hạn như hàm tạo), bạn sẽ suy nghĩ hai lần trước khi thêm tất cả các trường này và có thể bạn sẽ gói chúng vào một lớp khác và sử dụng @ConfigurationProperties
.
Làm cho lớp của bạn có thể kiểm tra cả đơn nhất và tích hợp
Để có thể viết cả các bài kiểm tra đơn vị đơn giản (không có bộ chứa lò xo đang chạy) và các bài kiểm tra tích hợp cho lớp thành phần Spring của bạn, bạn phải làm cho lớp này có thể sử dụng được có hoặc không có Spring.
Chạy một container trong một bài kiểm tra đơn vị khi không cần thiết là một cách làm tồi tệ làm chậm các bản dựng cục bộ: bạn không muốn điều đó.
Tôi đã thêm câu trả lời này vì không có câu trả lời nào ở đây dường như cho thấy sự khác biệt này và vì vậy họ dựa vào một container đang chạy một cách có hệ thống.
Vì vậy, tôi nghĩ rằng bạn nên di chuyển thuộc tính này được xác định là nội bộ của lớp:
@Component
public class Foo{
@Value("${property.value}") private String property;
//...
}
vào một tham số hàm tạo sẽ được Spring chèn vào:
@Component
public class Foo{
private String property;
public Foo(@Value("${property.value}") String property){
this.property = property;
}
//...
}
Ví dụ kiểm tra đơn vị
Bạn có thể khởi tạo Foo
mà không cần Spring và thêm bất kỳ giá trị nào để property
cảm ơn nhà xây dựng:
public class FooTest{
Foo foo = new Foo("dummyValue");
@Test
public void doThat(){
...
}
}
Ví dụ kiểm tra tích hợp
Bạn có thể tiêm thuộc tính trong ngữ cảnh với Spring Boot theo cách đơn giản này nhờ properties
thuộc tính của @SpringBootTest
:
@SpringBootTest(properties="property.value=dummyValue")
public class FooTest{
@Autowired
Foo foo;
@Test
public void doThat(){
...
}
}
Bạn có thể sử dụng thay thế @TestPropertySource
nhưng nó thêm một chú thích bổ sung:
@SpringBootTest
@TestPropertySource("property.value=dummyValue")
public class FooTest{ ...}
Với Spring (không có Spring Boot), nó sẽ phức tạp hơn một chút nhưng vì tôi đã không sử dụng Spring mà không có Spring Boot từ lâu nên tôi không thích nói một điều ngu ngốc.
Như một lưu ý phụ: nếu bạn có nhiều @Value
trường để đặt, trích xuất chúng vào một lớp được chú thích có @ConfigurationProperties
liên quan hơn vì chúng ta không muốn một hàm tạo có quá nhiều đối số.