展露頭腳
springboot的一大特點就是方便姜胖,今天來看看 @Condition 帶給我們什么樣的方便罚斗。
首先來寫一個接口副渴。
public interface AService {
void test();
}
接下來調(diào)用接口
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Application.class);
AService bean = run.getBean(AService.class);
bean.test();
}
}
接下來就差實現(xiàn) AService 了铸磅,我希望有三種不同的實現(xiàn)。
@Service()
public class AService1 implements AService {
public void test() {
System.out.println("AService1");
}
}
@Service()
public class AService2 implements AService{
public void test() {
System.out.println("AService2");
}
}
@Service()
public class DefaultAService implements AService {
public void test() {
System.out.println("DefaultAService");
}
}
我們先來運行一下
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'playground.service.AService' available: expected single matching bean but found 3: AService1,AService2,defaultAService
因為有三個不同的實現(xiàn)類溅潜,spring沒法明白我們到底要把哪個加入到容器中,當(dāng)調(diào)用AService的test方法時薪伏,用哪一個滚澜。
所以需求場景,就變成了嫁怀,我可以在配置文件中二選一(AService1设捐,AService2),如果沒有選就用默認(rèn)的塘淑。
這里主要用到三個注解
@ConditionalOnProperty()
@Service()
@ConditionalOnMissingBean()
如果在配置文件中找到 AServiceType = 1 的配置萝招,那么就載入一個 name = AService type=AService1 的bean到ioc容器。
@ConditionalOnProperty(value = "AServiceType", havingValue = "1")
@Service("AService")
public class AService1 implements AService {
public void test() {
System.out.println("AService1");
}
}
如果在配置文件中找到 AServiceType = 2 的配置存捺,那么就載入一個 name = AService type=AService2 的bean到ioc容器槐沼。
@ConditionalOnProperty(value = "AServiceType", havingValue = "2")
@Service("AService")
public class AService2 implements AService {
public void test() {
System.out.println("AService2");
}
}
如果沒有發(fā)現(xiàn) name=AService 的bean的話,則加載一個type=DefaultAService的bean到ioc容器捌治。
@ConditionalOnMissingBean(name = "AService")
@Service
public class DefaultAService implements AService {
public void test() {
System.out.println("DefaultAService");
}
}
如果 application.properties 沒有 AServiceType=(1 or 2)
output : DefaultAService
如果 application.properties 中 AServiceType=1
output : AService1
如果 application.properties 中 AServiceType=2
output : AService2
可以看到 @Conditional 的功能岗钩,就是在不同條件下,指導(dǎo)加載器肖油,要構(gòu)建哪些bean加入到ioc容器兼吓。
先來看看@Conditional的部分派生
@ConditionalOnBean(僅僅在當(dāng)前上下文中存在某個對象時,才會實例化一個Bean)
@ConditionalOnClass(某個class位于類路徑上森枪,才會實例化一個Bean)
@ConditionalOnExpression(當(dāng)表達式為true的時候视搏,才會實例化一個Bean)
@ConditionalOnMissingBean(僅僅在當(dāng)前上下文中不存在某個對象時,才會實例化一個Bean)
@ConditionalOnMissingClass(某個class類路徑上不存在的時候县袱,才會實例化一個Bean)
@ConditionalOnNotWebApplication(不是web應(yīng)用)
其他略 都是@Conditional*
那么當(dāng)已有功能不能滿足你的殘暴需求的時候浑娜,怎么辦呢?
我們隨便點開兩個@Conditional的派生注解看看
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty
OnBeanCondition.class 显拳,OnPropertyCondition.class
最終都是實現(xiàn) Condition 接口棚愤,然后再上面做各種不同的擴展。
代碼有點多杂数,這里就不貼了宛畦。說白了我們可以自定義條件,實現(xiàn)Condition接口揍移,來定制復(fù)雜的加載條件次和。(我覺得springboot提供的條件已經(jīng)完全夠用了)