有這樣一種場景,對接短信供應商,須要可以根據配置自動切換具體的供應商,java
而Spring@Conditional恰好能夠爲咱們實現此功能ide
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Conditional { Class<? extends Condition>[] value(); // 這裏須要實現Condition接口 }public class UCloudConditional implements Condition { private Logger log = LoggerFactory.getLogger(UCloudConditional.class); private Properties properties; @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { properties = new Properties(); InputStream is = null; try { is = conditionContext.getResourceLoader().getResource("classpath:xxx.properties").getInputStream(); properties.load(is); return StringUtils.isEmpty(properties.getProperty("sms.used")) ? false : SupplierConstant.UCLOUD.equalsIgnoreCase(properties.getProperty("sms.used")); } catch (Exception e) { log.error("UCloudConditional#matches, load properties fail,e:", e); return false; } finally { if (is != null) { try { is.close(); } catch (IOException e) { log.error("UCloudConditional#matches, load properties fail,e:", e); } } } }public class ClConditional implements Condition { private Properties properties; @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { properties = new Properties(); InputStream is = null; try { is = conditionContext.getResourceLoader().getResource("classpath:xxx.properties").getInputStream(); properties.load(is); return StringUtils.isEmpty(properties.getProperty("sms.used")) ? true : SupplierConstant.CHUANG_LAN.equalsIgnoreCase(properties.getProperty("sms.used")); } catch (Exception e) { log.error("ClConditional#matches, load properties fail,e:", e); return true; // CL做爲默認使用的短信服務商 } finally { if (is != null) { try { is.close(); } catch (IOException e) { log.error("ClConditional#matches, load properties fail,e:", e); } } } }@Configuration public class SMSMessageConfiguration { @Bean @Conditional(UCloudConditional.class) public ISendMessageTemplate createUCloudTemplate() { return new UCloudSendMessageTemplate(); } @Bean @Conditional(ClConditional.class) public ISendMessageTemplate createClTemplate() { return new ClSendMessageTemplate(); } }public interface ISendMessageTemplate { BaseResponse sendMessage(String phone, String content); }@Service public class SendMessageAdapter { private ISendMessageTemplate sendMessageTemplate; @Autowired public SendMessageAdapter(ISendMessageTemplate sendMessageTemplate) { this.sendMessageTemplate = sendMessageTemplate; } /** * 短信發送 * * @param phone * @param content * @return */ public BaseResponse sendMessage(String phone, String content) { return this.sendMessageTemplate.sendMessage(phone, content); } }#SpringBoot中的作法this
/**使用配置化的方式參與感更強,但須要更多額外的配置來處理, * 而使用Boot的方式提供一種開箱即用的機制相對來講更加靈活,只須要注入相關依賴或者 * 取消相關依賴便可 **/ @Primary @Bean @ConditionalOnClass(value = xxx.xx.x.SendUSMSMessageParam.class) public ISendMessageTemplate createUCloudTemplate() { return new UCloudSendMessageTemplate(); } @ConditionalOnMissingClass(value = "xxx.xx.x.SendUSMSMessageParam") @Bean public ISendMessageTemplate createClTemplate() { return new ClSendMessageTemplate(); }