问题由来:
springboot项目中使用加解密功能,密钥在application.properties文件中配置,因此加解密服务类需要读取该变量,为了提高效率,加解密服务类静态初始化的时候就生成了SecretKeySpec(不是每次调用加密或者解密方法时再生成SecretKeySpec)。 如果我们使用如下方式读取配置文件,然后赋值给mySecretKey, springboot就会报@Autowired annotation is not supported on static fields
public class EnDecryptionServiceImpl implements IEnDecryptionService{
@Value("${mySecretKey}")
private static String mySecretKey;
...
static {
try {
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
ivspec = new IvParameterSpec(iv);
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
...
这里用到了mySecretKey。 因此必须把mySecretKey设置为static
}
catch (NoSuchPaddingException ex) {
log.error("no PKCS5Padding in the jvm", ex);
}
catch (NoSuchAlgorithmException ex) {
log.error("no AES algorithm in the jvm", ex);
}
catch (Exception ex) {
log.error("generic exception", ex);
}
}
...
问题表现:
程序日志提示@Autowired annotation is not supported on static fields, 并且原先读取到的mySecretKey为null。
解决方法:
给EnDecryptionServiceImpl 增加一个setMySecretKey,然后在该set方法上面加@Autowired即可。
注意:因为我的setMySecretKey(String secretKey)需要一个字符串bean, 因此额外添加一个config生成一个String bean。
@Autowired
public void setMySecretKey(String secretKey) {
mySecretKey = secretKey;
log.info("set mySecretKey={}", mySecretKey);
init();
}
生成String bean
@Configuration
@Slf4j
public class MySecretConfig {
@Value("${mySecretKey:defatulValue}")
private String mySecretKey;
@Bean
public String getMySecretKeyFromCfg() {
return mySecretKey;
}
}
通过日志可以发现,EnDecryptionServiceImpl 类的静态变量mySecretKey已经顺利获取到application.properteis中的值了。
完整的代码在[这里](https://github.com/yqbjtu/springboot/tree/master/CLRDemo)
。您只需要关注EnDecryptionServiceImpl 类的静态变量如何被赋值的,其余的只是springboot为了演示效果而写的完整程序的代码。
网友评论