5s quảng cáo
Mình có 1 shopee nho nhỏ bán ốp iPhone kunn.oops, mọi người ủng hộ nhé :D
Giới thiệu
Khi xây dựng một chương trình với Spring Boot đôi lúc chúng ta một Bean chỉ được load lên hoặc khởi tạo theo một điều kiện nào đó. Ví dụ như tạo một Bean trong môi trường Test, còn môi trường thật sẽ không cần nữa.
Spring Boot hỗ trợ chúng ta làm điều này với Annotation @Conditional
.
Bài này yêu cầu kiến thức cơ bản:
Toàn bộ ví dụ trong bài viết này đều có tại Github
Cách tạo bean có điều kiện
Trong Spring Boot, có rất nhiều cách để tạo ra Bean
, bạn biết cách nào?
@Component
, @Configuration
, @Bean
, @Service
, v.v...
Với tất cả các cách tạo ra Bean
, bạn đều có thể thêm một hoặc nhiều điều kiện để cho việc tạo ra Bean
đó chỉ xảy ra nếu nó thỏa mãn một điều kiện cho trước.
SpringBoot hỗ trợ rất nhiều loại điều kiện khác nhau, tất cả đều sẽ bắt đầu bằng tiền tố @Conditional...
. Còn hậu tố thì chúng ta sẽ đề cập sau.
Cách thức hoạt động của tất cả @Condition
như sau:
@Configuration public class ConditionalOnBeanExample { /* ABeanWithCondition chỉ được tạo ra khi @Condition thỏa mãn */ @Bean @Conditional... ABeanWithCondition aBeanWithACondition() { return new ABeanWithCondition(); } }
Nếu bạn gắn nó trên một @Configuration
thì toàn bộ các @Bean
bên trong sẽ bị chịu tác động.
@Conditional... @Configuration public class ConditionalOnBeanExample { /* SomeOtherBean chỉ được tạo ra khi @Condition thỏa mãn */ @Bean SomeOtherBean someOtherBean() { return new SomeOtherBean(); } /* SomeOtherBean2 chỉ được tạo ra khi @Condition thỏa mãn */ @Bean SomeOtherBean2 someOtherBean2() { return new SomeOtherBean2(); } }
Tương tự cho tất cả các annotation khác như @Component
, @Service
, @Repository
@Conditional... @Component public class ConditionalOnBeanExample { }
Bây giờ chúng ta sẽ đi tìm hiểu các loại điều kiện trong Spring Boot.
@ConditionalOnBean
@ConditionalOnBean
sử dụng khi chúng ta muốn tạo ra một Bean, chỉ khi có một Bean khác đang tồn tại
@Configuration public class ConditionalOnBeanExample { /* Đây là một Bean, bạn hãy chạy ứng dụng khi comment và chạy lại lần nữa nhưng bỏ dấu comment phía dưới để xem kết quả. */ // @Bean RandomBean randomBean() { return new RandomBean(); } /* ABeanWithCondition chỉ được tạo ra, khi RandomBean tồn tại trong Context. */ @Bean @ConditionalOnBean(RandomBean.class) ABeanWithCondition aBeanWithACondition() { return new ABeanWithCondition(); } }
@ConditionalOnProperty
Dùng @ConditionalOnProperty
khi bạn muốn quyết định sự tồn tại Bean thông qua cấu hình property.
@Configuration public class ConditionalOnPropertyExample { /* @ConditionalOnProperty giúp gắn điều kiện cho @Bean dựa theo property trong config */ @Bean @ConditionalOnProperty( value="loda.bean2.enabled", havingValue = "true", // Nếu giá trị loda.bean2.enabled = true thì Bean mới được khởi tạo matchIfMissing = false) // matchIFMissing là giá trị mặc định nếu không tìm thấy property loda.bean2.enabled ABeanWithCondition2 aBeanWithCondition2(){ return new ABeanWithCondition2(); } }
application.properties
#Thay đổi thành true để tạo bean2 loda.bean2.enabled=true
@ConditionalOnExpression
Trong trường hợp bạn muốn thỏa mãn nhiều điều kiện trong property, hãy sử dụng @ConditionalOnExpression
@Configuration @ConditionalOnExpression( "${loda.expression1.enabled:true} and ${loda.expression2.enabled:true}" ) public class ConditionalOnExpressionExample { }
@ConditionalOnMissingBean
Nếu trong Context
chưa tồn tại bất kỳ Bean nào tương tự, thì @ConditionalOnMissingBean
sẽ thỏa mãn điều kiện và tạo ra một Bean như thế.
@Configuration public class ConditionalOnMissingBeanExample { /** * Nếu trong Context chưa tồn tại một SomeMissingBean nào * Thì Bean ở dưới đây mới được tạo * @return */ @ConditionalOnMissingBean DataSource someMissingBean(){ return new DataSource(); } }
@ConditionalOnResource
@ConditionalOnResource
thỏa mãn khi có một resources nào đó do bạn chỉ định tồn tại
/* Nếu Spring Boot không tìm thấy file application.properties thì class này không được tạo */ @Configuration @ConditionalOnResource(resources = "/application.properties") public class ConditionalOnResourceExample { }
@ConditionalOnClass
@ConditionalOnClass
thỏa mãn khi trong classpath có tồn tại class mà bạn yêu cầu
@Configuration @ConditionalOnClass(name = "daothaison.me.spring.LodaHandsome") class ConditionalOnClassExample { }
@ConditionalOnMissingClass
@ConditionalOnMissingClass
ngược lại với @ConditionalOnClass
. thỏa mãn khi trong classpath không tồn tại class mà bạn yêu cầu
@Configuration @ConditionalOnMissingClass(name = "daothaison.me.spring.LodaHandsome") class ConditionalOnMissingClassExample { }
@ConditionalOnJava
@ConditionalOnJava
thỏa mãn nếu môi trường chạy version Java đúng với điều kiện
@Configuration @ConditionalOnJava(JavaVersion.EIGHT) class ConditionalOnJavaExample { }
Một số loại khác
Vẫn còn các bạn ạ, những mình thấy nó ít khi được sử dụng, nên sẽ không đề cập, tránh loạn thông tin.
Custom Conditional
Tất nhiên là bạn hoàn toàn có thể tự tạo ra cho mình một điều kiện. Mình sẽ đề cập cách làm ở bài sau.
Kết
Và như mọi khi, toàn bộ code đều được up lên Github.