当前栏目
结合springboot条件注入@ConditionalOnProperty以及@ConfigurationProperties来重构优化代码
@ConditionalOnProperty实现按需注入bean
短信工具类 SmsUtil
zhenghe-common是一个基础包。
SmsUtil坐落在zhenghe-common里。先看看Smsutil的面目。
package com.emax.zhenghe.common.util; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @Slf4j @Configuration public class SmsUtil { @Value("${smtp.config.username}") private String userName; @Value("${smtp.config.requestAddress}") private String requestAddress; @Value("${smtp.config.password}") private String passWord; @Value("${smtp.config.oem.username:oem}") private String oemUserName; @Value("${smtp.config.oem.password:oemsdfaaskdlkfk15673%!@4}") private String oemPassWord; /** * 发送短信 * @param phone 手机号 * @param msg 短信内容 * @return */ public String sendSMS(String phone, String msg) { StringBuilder sbParam = new StringBuilder(); StringBuilder url = new StringBuilder(); try { sbParam.append("?account=").append(userName); sbParam.append("&pwd=").append(URLEncoder.encode(passWord, "UTF-8")).append("&mphone=").append(phone).append("&content=") .append(URLEncoder.encode(msg, "UTF-8")); url.append(requestAddress) .append(sbParam.toString()); Integer result = HttpClientUtils.requestByGetMethod(url.toString()); return result.toString(); } catch (Exception e) { e.printStackTrace(); log.error("发送短信异常", e); } return "信息发送成功!"; } /** * 发送短信 */ public String sendSMS(String phone, String msg,String userName,String passWord) { ... } /** * 发送短信 */ public String sendOemSMS(String phone, String msg, String smsSign) { StringBuilder smsSignBuilder = new StringBuilder(); smsSignBuilder.append("【") .append(smsSign) .append("】") .append(msg); return sendSMS(phone, smsSignBuilder.toString(), oemUserName, oemPassWord); } }
这里要说的是上面通过@Value注入的field。
存在的问题是:这要求所有依赖了zhenghe-common并扫描com.emax.zhenghe.common.util包的应用,都必须定义那些短信相关的properties配置。
需要改进的是:这些properties都以smtp.config开头,所以使用spring-beans的@Value显得啰嗦,不如使用spring-boot的@ConfigurationProperties。
先看问题-有的应用不涉及到收发短信,可以不用配置短信相关的这些properties。
解决办法就是spring-boot-autoconfigure的@ConditionalOnProperty注解。
@ConditionalOnProperty注解是spring-boot-autoconfigure下“条件注入”的重要成员,根据配置参数,来决定是否需要创建bean。它主要是通过自身的两个属性来控制自动配置是否生效,这两个属性分别是name、havingValue。只有当配置文件(application.properties或者bootstrap.yml)中和name相同的属性的值和注解上havingValue的值相同时,该配置文件才会生效。
敲黑板,@ConditionalOnProperty并不继承@Configuration,它只是控制bean是否生效的,所以@Configuration注解还是需要加在SmsUtil头上的。
如下是@ConditionalOnProperty的javadoc
仔细看javadoc,就能找到答案。这里,我们的改造方案是
@ConditionalOnProperty(prefix = "smtp.config",name = "requestAddress") |
下面方式也行,但是不如上面的易读。
@ConditionalOnProperty( name = "smtp.config.requestAddress") |
@Configuration是spring-context-**.jar的成员,继承@Component。
spring-context包里下面的这些注解,你一定知道。
+- context
| +- annotation
| | +- Bean
| | +- ComponentScan
| | +- Configuration
| | +- Import
| | +- Lazy
| | +- Primary
| | +- Profile
| | +- Scope
+- stereotype
| +- Service
| +- Component
| +- Controller
| +- Repository
而 @Value @Autowired 在 spring-beans-**.jar包里(package:org.springframework.beans.factory.annotation); @Mapping @PutMapping @ResponseBody @RestController etc., 在spring-web-**.jar包里(package:org.springframework.web.bind.annotation)。
BTW,@Service 与 @Component 的区别
再说改进项:@ConfigurationProperties取代@Value
org.springframework.boot.context.properties.ConfigurationProperties在spring-boot-**.jar里。用法很easy,指定prefix即可。
需要指明的是,setter方法还是要有的。这里使用lombok的@Setter注解。
其中,oemUserName与property配置项的名称不一致,需要单独用@Value指定,并且value必须用全名 : @Value("${smtp.config.oemName:null}")。
改造后的SmsUtil
package com.emax.zhenghe.common.util; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Slf4j //↓↓ 声明bean @Configuration(value = "smsUtil") @ConditionalOnProperty(prefix = "smtp.config", name = "requestAddress") //↓↓ properties配置 @ConfigurationProperties(prefix = "smtp.config") @Setter//必须有setter才能为field赋上值 public class SmsUtil { private String userName; private String requestAddress; private String password; @Value("${smtp.config.oemName:null}") private String oemUserName; private String oemPassWord; /** * 发送短信 */ public String sendSMS(String phone, String msg) { ... } /** * 发送短信 */ public String sendSMS(String phone, String msg,String userName,String passWord) { ... } /** * 发送短信 */ public String sendOemSMS(String phone, String msg, String smsSign) { ... } }
相关文章
- vue+element-ui前端使用print-js实现打印,可自定义样式(横纵向,缩放比,字体大小,背景色)
- 一篇文章吃透 CSS3 属性: transition过渡 与 transform动画
- Vue+element ui实现好看的个人中心
- 【一起学Rust | 框架篇 | Viz框架】轻量级 Web 框架——Viz
- Vue3 + Element Plus 按需引入 - 自动导入
- JS数组方法中哪些会改变原数组,哪些不会?
- Vue--》搭配Bootstrap实现Vue的列表增删功能
- 【数字孪生】UE4虚幻引擎与前端Web页面的结合
- Lodash 使用及常用方法
- VUE 中项目启动没有问题,代码中 script 标签有蓝色波浪线标注
- css点击文字(非按钮) 能自动改变颜色。
- Vue3中修改父组件传递到子组件中的值(全网少有)
- 实现Vue按钮(button)绑定回车(enter)事件
- 设置背景图片大小的方法
- Spring Boot实现任意位置的properties及yml文件内容配置与获取
- Element Plus的el-tree-select组件,懒加载 + 数据回显
- Vue2与Vue3共存于一台电脑 保姆级教程
- js截取字符串开头、结尾、以及两字符串之间的内容
- JavaScript:实现复制粘贴剪切功能
- 《中秋佳节倍思亲》——2022年这场中秋