SpringBoot框架,使用一些注解,能够快速进行开发,比如在配置文件application.yml中设置自定义参数,然后在业务开发时开发时使用注解@Value,就可以获取到配置文件中的参数值。
但是对于某些业务,传递的参数必须是静态变量,这时候我们发现,直接在参数上添加注解@Value,根本获取不到值,返回的值为null。这是为什么呢?该如何使用注释对静态变量赋值呢?
原因:springboot不支持把值赋值给静态变量,因为静态变量不属于对象,只属于类,也就是说在类被加载字节码的时候变量已经初始化了,也就是给该变量分配内存了,导致spring忽略静态变量。所以这种写法就是错误的,这样是无法注入的,在使用该变量的时候会导致空指针错误:
解决方案:使用@Value 在set 方法去赋值 ,并且 set方法不能声明为statis。注意set方法的参数可以任意命名,但不能跟属性名相同。
举例说明,我在项目中配置了redis哨兵集群,需要使用application.yml中的配置,并且使用的变量需是静态变量。
application.yml中的redis模块的配置如下:
redis:
password: root
timeout: 5000
jedis:
pool:
# 最大连接数
max-active: 100
# 最大阻塞等待时间ms(负数表示没有限制)
max-wait: 10000
# 最大空闲连接
max-idle: 20
# 最小空闲连接
min-idle: 8
sentinel:
master: mymaster
# 哨兵的IP:Port列表
nodes:127.0.0.1:26379;127.0.0.1:26380;127.0.0.1:26381
Redis静态变量赋值的类如下(小细节:set方法参数名与属性名设置不同):
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author 编程侠
* @projectName springboot
* Redis 静态变量配置类
*/
@Component
public class RedisConnectConfig {
public static String MAX_ACTIVE;
public static String MAX_IDLE;
public static String MAX_WAIT;
public static String MASTER;
public static String NODES;
public static String TIMEOUT;
public static String PASSWORD;
//使用@Value 注入静态参数 只能在set 方法去赋值 , set方法不能是statis
@Value("${spring.redis.jedis.pool.max-active}")
private void setMaxActive(String maxActive){
MAX_ACTIVE = maxActive;
}
@Value("${spring.redis.jedis.pool.max-idle}")
private void setMaxIdle(String maxIdle){
MAX_IDLE = maxIdle;
}
@Value("${spring.redis.jedis.pool.max-wait}")
private void setMaxWait(String maxWait){
MAX_WAIT = maxWait;
}
@Value("${spring.redis.sentinel.master}")
private void setMaster(String master){
MASTER = master;
}
@Value("${spring.redis.sentinel.nodes}")
private void setNODES(String nodes){
NODES = nodes;
}
@Value("${spring.redis.timeout}")
private void setTIMEOUT(String timeout){
TIMEOUT = timeout;
}
@Value("${spring.redis.password}")
private void setPASSWORD(String password){
PASSWORD = password;
}
}
使用redis的静态变量类如下:
static {
try {
if (shardedJedisSentinelPool == null) {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
int max_total = Integer.parseInt(RedisConnectConfig.MAX_ACTIVE);
config.setMaxTotal(max_total);
int max_idle = Integer.parseInt(RedisConnectConfig.MAX_IDLE);
config.setMaxIdle(max_idle);
int max_wait = Integer.parseInt(RedisConnectConfig.MAX_WAIT);
config.setMaxWaitMillis(max_wait);
List<String> masters = new ArrayList<String>();
Set<String> sentinels = new HashSet<String>();
String masterName = RedisConnectConfig.MASTER;
String hostAndPort = RedisConnectConfig.NODES;
for (String strMaster : masterName.split(";")) {
masters.add(strMaster.trim());
}
for (String strHostAndPort : hostAndPort.split(";")) {
sentinels.add(strHostAndPort.trim());
}
int timeout = Integer.parseInt(RedisConnectConfig.TIMEOUT);
String password = RedisConnectConfig.PASSWORD;
shardedJedisSentinelPool = new ShardedJedisSentinelPool(masters, sentinels, config, timeout,password);
}
} catch (Exception e) {
e.printStackTrace();
}
}
我们也可以在同一个类中既声明普通变量,又声明静态变量:
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* 支付宝扫码支付
*/
@Configuration
@Data
public class AlipayScanConfig {
/**************普通变量,使用@Value()作用在参数上即可*******************/
@Value("${alipay.scan.timeoutExpress}")
private String timeoutExpress;
@Value("${alipay.scan.charset}")
private String charset;
@Value("${alipay.scan.format}")
private String format;
@Value("${alipay.scan.notifyUrl}")
private String notifyUrl;
@Value("${alipay.scan.downloadPath}")
private String downloadPath;
/**************静态变量,使用@Value 注入静态参数 只能在set方法去赋值 , set方法不能是statis*******************/
public static String ZFBINFO_PROPERTIES;
@Value("${alipay.scan.zfbinfoProperties}")
private void setZfbinfoProperties(String zfbinfoProperties){
ZFBINFO_PROPERTIES = zfbinfoProperties;
}
}
在使用时有点不太一样
普通变量:
@Autowired
private AlipayWithholdConfig alipayWithholdConfig;
alipayWithholdConfig.getNotifyUrl();//通过get方法取值
静态变量,直接在类上取变量:
@Autowired
private AlipayWithholdConfig alipayWithholdConfig;
AlipayWithholdConfig.appId;//直接取属性