文章目录
前言
建议先了解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。