Bootstrap

spring中使用@value注入static静态字符串变量

前言

建议先了解spring的依赖注入的正常使用,参考我的另一篇文章spring中依赖注入@Value和@Autowired的使用

问题

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
@Component
public class SystemUtil {
    @Value("${login.url}")
    public static String LOGIN_URL;
}

运行时发现静态属性LOGIN_URL的值为null,@Value注入失败。

分析

Spring是不能直接在static变量上使用@value为其注入值的,因为Spring的依赖注入是依赖setter方法,setter方法是属于对象的,而static变量是属于类的。

解决

方式一:@Value+setter

再加一个有@Value注解的就一个参数的非静态方法,方法内将参数值赋给静态变量。这是在Spring的bean的生命周期中的属性赋值阶段执行注入。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
@Component
public class SystemUtil {
    public static String LOGIN_URL;
	@Value("${login.url}")
	public void setLoginUrl(String loginUrl) {
        LOGIN_URL = loginUrl;
    }

方式二:@Value + @PostConstruct

再声明一个实例变量,将@Value移到该实例变量上,再加一个@PostConstruct注解的方法,方法内将该实例变量的值赋给静态变量。这是在Spring的bean的生命周期中的初始化前置处理阶段执行注入。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
@Component
public class SystemUtil {
    //@Value("${login.url}")
    public static String LOGIN_URL;
    @Value("${login.url}")
	private String loginUrl;
	
	@PostConstruct
	public void init() {
		LOGIN_URL = this.loginUrl;
	}
}

方式三:@Value + InitializingBean接口

这是在Spring的bean的生命周期中的初始化阶段执行注入。

@Component
public class SystemUtil implements InitializingBean {
    //@Value("${login.url}")
    public static String LOGIN_URL;
	@Value("${login.url}")
	private String loginUrl;
	
	@Override
    public void afterPropertiesSet() throws Exception {
        LOGIN_URL = loginUrl;      
    }
}

方式四:@Value + init-method

如果是使用xml方式或者@Bean方式注册的SystemUtil bean,就可以为它自定义初始化方法了。这也是在Spring的bean的生命周期中的初始化阶段执行注入,并在InitializingBean#afterPropertiesSet()的后面执行。

@Configuration
public class RootConfig() {
	@Bean(initMethod="myInit")
	public SystemUtil systemUtil() {
		return new SystemUtil();
	}
}

@Component
public class SystemUtil {
    //@Value("${login.url}")
    public static String LOGIN_URL;
    @Value("${login.url}")
	private String loginUrl;
	
	public void myInit() {
		LOGIN_URL = this.loginUrl;
	}
}

注意

无论用哪种方式,都请确保程序在创建这个bean实例之前不会访问SystemUtil.LOGIN_URL,因为此时它的值还是null。

其他

参考【Spring】bean的三种初始化方法及它们的执行顺序

;