在日常開發中,存在着這種一種場景,框架對接口A提供了一個種默認的實現AImpl,隨着需求的變更,現今AImpl不能滿足了功能需要,這時,我們該怎么辦? 當然是修改AImpl的實現代碼了,但是,如果它是第三方依賴呢? 或者說,我們自己寫了的某個功能模塊,AImpl是我們為此模塊提供的一種默認實現,用戶可以使用它,也可以按需求進行覆蓋(或者說是擴展),該怎么辦?
對此,spring為我們提供了@Conditional注解,使用它可以很好的解決此類問題。
下面,舉個例子。 有個RandomGenerator接口,接口里面有個generator()方法生成隨機字符串,有兩個實現類StringRandomGenerator和NumberRandomGenerator, 其中StringRandomGenerator是默認實現。也就是說,在我們不配置NumberRandomGenerator時,程序使用StringRandomGenerator生成隨機字符串,在我們有配置NumberRandomGenerator時,程序使用NumberRandomGenerator生成隨機字符串。
/** * 生成隨機字符串的頂層接口 */ public interface RandomGenerator { Object generator(); }
import org.apache.commons.lang.RandomStringUtils; public class StringRandomGenerator implements RandomGenerator { @Override public Object generator() { char[] chars = {'a','b','c','d','e','f','g'}; String random = RandomStringUtils.random(5, chars); return "StringRandomGenerator:"+random; } }
/** * 將NumberRandomGenerator 注冊成spring bean時,StringRandomGenerator 失效 * 相當於是NumberRandomGenerator中的generator方法覆蓋了 StringRandomGenerator 中的generator方法 */ @Component public class NumberRandomGenerator implements RandomGenerator { @Override public Object generator() { String random = RandomStringUtils.random(5, true, true); return "NumberRandomGenerator:" + random; } }
/** * 配置類 */ @SpringBootConfiguration public class RandomGeneratorConfig { /** * @ConditionalOnMissingBean(value = RandomGenerator.class) * 該注解的意思是: 如果Ioc容器中沒有 RandomGenerator 類型的 bean時 * 就將StringRandomGenerator注冊到Ioc容器中 */ @Bean @ConditionalOnMissingBean(value = RandomGenerator.class) public RandomGenerator stringRandomGenerator() { return new StringRandomGenerator(); } }
最后寫個controller來測試一把
@RestController public class RandomController { @Autowired private RandomGenerator randomGenerator; @GetMapping("/random") public Object random() { return randomGenerator.generator(); } }
在將NumberRandomGenerator 注冊到Ioc容器的情況下,測試結果如下:

接下來,我們將NumberRandomGenerator類上中@Component注解干掉,再測試

完美!
