java 静态代码块和spring @value等注解注入顺序
java 静态代码块和 spring @value 等注解注入顺序
问题所在
先上代码
java 方法
@Value("${mf.cashost}")
public static String casHost;
public static String getCasHost() {
if (StringUtils.isEmpty(casHost)) {
//casHost = "http://sso.abc.com.cn/sso/";
casHost = "http://ssotest.abc.com.cn/sso/";
}
return casHost;
}
配置文件
mf.cashost=http://sso.abc.com.cn/sso/
正常我们想要的getCasHost
的值,肯定是sso.abc.com.cn
,而不是ssotest
,但是如果调用getCasHost
肯定是返回test
的,或者说,casHost 最开始进到 getCasHost 的方法时,就是空的。
分析一波
关于实例变量与构造方法的初始化顺序问题
- Java 类会先执行构造方法,然后再给注解了 @Value 的属性注入值,所以在执行静态代码块的时候,就会为 null。
- Java 及 Spring 初始化顺序:java 静态属性 / 静态代码块 (根据声明的先后顺序加载)、构造代码块、 构造方法(即:spring 创建 FetchStockSchedule 的实例 交给 Spring 管理 )、@Value/@ AutoWired/@Resouce 等注解 的成员变量等赋值。
解决一下
解决方案
- 首先,让当前类变成 Spring 的 bean,
- 再使用 @PostConstruct
@Value("${mf.cashost}")
private String mfCasHost;
private static String casHost;
@PostConstruct
public void init() {
casHost = mfCasHost;
}
public static String getCasHost() {
if (StringUtils.isEmpty(casHost)) {
casHost = "http://ssotest.abc.com.cn/sso/";
}
return casHost;
}
原理
Java 中该注解的说明: @PostConstruct
该注解被用来修饰一个非静态的void()
方法。被@PostConstruct
修饰的方法会在服务器加载Servlet
的时候运行,并且只会被服务器执行一次。PostConstruct 在构造函数之后执行,init() 方法之前执行。
通常我们会是在 Spring 框架中使用到 @PostConstruct 注解 该注解的方法在整个 Bean 初始化中的执行顺序:
此时的执行顺序:
- 构造方法
- Before Initialization
- 使用 PostConstruct 注解
- InitializingBean 接口
- init-method 指定的初始化方法
- After Initialization