[Spring Boot] Hướng dẫn tự tạo custom @Conditional
Bài đăng này đã không được cập nhật trong 5 năm
Nguồn: loda.me
Giới thiệu
Yêu cầu bạn phải đọc bài viết về @Conditional
trước:
Tôi đã giới thiệu với các bạn các sử dụng các loại @Conditional
có sẵn trong Spring Boot. Tuy nhiên, trên thực tế, sẽ có những lúc yêu cầu các loại điều kiện nằm ngoài phạm vi của Spring Boot cung cấp.
Khi đó, chúng ta phải tự tạo @Condinal
cho mình.
Tự tạo @Conditional
Nguồn: https://loda.me - còn nhiều cái hay ho lắm!
Để tạo ra một điều kiện cho mình, bạn cần kế thừa lớp Condition
, và implement lại function matches
matches
là nơi bạn kiểm tra điều kiện xem có thoả mãn không.
/*
Một điều kiện, phải kế thừa lớp Condition của Spring Boot cung cấp
*/
public class WindowRequired implements Condition{
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// Nếu OS ra window trả ra true.
return System.getProperty("os.name").toLowerCase().contains("win");
}
}
Và khi đã định nghĩa được cho mình một điều kiện riêng, bạn có thể sử dụng như sau:
@Configuration
public class AppConfiguration {
public static class SomeBean{
}
/*
SomeBean chỉ được tạo ra khi
thỏa mãn điều kiện
*/
@Conditional(WindowRequired.class)
@Bean
SomeBean someBean(){
return new SomeBean();
}
}
Tự tạo Annotation @Conditional
Nếu việc viết @Conditional(WindowRequired.class)
chưa làm bạn hài lòng, bạn có thể tự tạo ra một Annotation
giống với Spring Boot.
Ví dụ như @ConditionalOnClass
trong bài viết trước
Thì hãy làm như sau:
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
// Đánh dấu annotation này bởi @Conditional(WindowRequired.class)
@Conditional(WindowRequired.class)
public @interface ConditionalOnWindow {
/*
Trong trường hợp bạn muốn viết ngắn gọn,
hay tạo ra 1 Annotation mới và gắn @Conditional(WindowRequired.class)
trên nó
Như vậy khi cần sử dụng chỉ cần gọi @ConditionalOnWindow là được
*/
}
Khi sử dụng:
@Configuration
public class AppConfiguration {
public static class SomeBean{
}
/*
SomeBean chỉ được tạo ra khi
thỏa mãn điều kiện
*/
@ConditionalOnWindow
@Bean
SomeBean someBean(){
return new SomeBean();
}
}
Chạy thử
@SpringBootApplication
public class App {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(App.class, args);
try {
SomeBean someBean = context.getBean(SomeBean.class);
System.out.println("SomeBean tồn tại!");
}catch (Exception e){
System.out.println("SomeBean chỉ được tạo nếu chạy trên Window");
}
}
}
Hãy bỏ Annotation @ConditionalOnWindow
đi và chạy thử, sau đó thêm lại, xem kết quả của 2 lần chạy.
Kết hợp nhiều điều kiện với OR
Bạn có thể kết hợp nhiều điều kiện với nhau bởi phép OR.
Spring Boot hỗ trợ điều này bằng cách kế thừa lớp AnyNestedCondition
/**
* Class kế thừa AnyNestedCondition sẽ chấp nhận mọi
* điều kiện @Conditional bên trong nó
*/
public class WindowOrMacRequired extends AnyNestedCondition{
public WindowOrMacRequired(){
super(ConfigurationPhase.REGISTER_BEAN);
}
/*
Bạn phải định nghĩa các Điều kiện bên trong class
kế thừa AnyNestedCondition
*/
@Conditional(WindowRequired.class)
public class RunOnWindow{}
/*
Lúc này, cả 2 điều kiện Window và Mac sẽ được kết hợp vs
nhau khi kiểm tra, nếu thoả mãn 1 trong 2 là đc
*/
@Conditional(MacRequired.class)
public class RunOnMac{}
}
Sử dụng
@Configuration
public class AppConfiguration {
public static class SomeBean{
}
/*
SomeBean chỉ được tạo ra khi
thỏa mãn điều kiện
*/
@Conditional(WindowOrMacRequired.class)
@Bean
SomeBean someBean(){
return new SomeBean();
}
}
Kết hợp nhiều điều kiện với AND
Bạn có thể kết hợp các điều kiện bằng phép AND bằng cách kế thừa lớp AllNestedConditions
.
Cách kế thừa của nó giống với AnyNestedCondition
nên tôi sẽ không cần đề cập thêm.
Ngoài ra, có một cách khác là sử dụng nhiều custom @Conditional
cùng một lúc.
@Bean
@ConditionalOnWindow
@Conditional(MacRequired.class)
SomeBean someBean() {
return new SomeBean();
}
Kết
Tới đây, bạn có thể nắm vững được cách tạo điều kiện cho cấu hình ứng dụng của mình, nó sẽ rất có ích khi bạn làm việc và tách biệt được hai môi trường dev và production.
Và như mọi khi, toàn bộ code đều được up lên Github. <i class="fab fa-github"></i>
All rights reserved