文章目录
spring初始化配置文件到常量类
spring不能注入static变量的原因:
Spring 依赖注入 是依赖 set方法
set方法是 是普通的对象方法
static变量是类的属性
因此,我们把配置文件想注入到静态常量类中时,就得想办法。
思路1、思路2 完成了配置文件到静态变量的注入,思路3 完成了对静态常量的赋值。
思路一:Spring中的InitializingBean
网上demo
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Config implements InitializingBean {
@Value("${policyFile.es.host}")
private String policyFileEsHost;
@Value("${policyFile.es.port}")
private String policyFileEsPort;
@Value("${policyFile.es.hostname}")
private String policyFileEsHostName;
@Value("${policyFile.es.password}")
private String policyFileEsPassword;
public static String POLICYFILE_ES_HOST;
public static String POLICYFILE_ES_PORT;
public static String POLICYFILE_ES_HOST_NAME;
public static String POLICYFILE_ES_PASSWORD;
@Override
public void afterPropertiesSet() throws Exception {
POLICYFILE_ES_HOST=policyFileEsHost;
POLICYFILE_ES_PORT=policyFileEsPort;
POLICYFILE_ES_HOST_NAME=policyFileEsHostName;
POLICYFILE_ES_PASSWORD=policyFileEsPassword;
}
}
具体思路,如代码所示,我们还是用普通的成员变量,完成注入,在afterPropertiesSet方法中,我们赋值给我们我们的静态成员变量。
但是,如果static成员变量用final修饰,经过测试,该方法行不通,因为
final修饰变量的初始化时机
- 显示初始化
- 在对象构造完毕前即可
InitializingBean接口用来定制初始化之后操作方法(afterPropertiesSet)。
可以看到,final变量初始化是要求非常靠前的。
Spring 容器中的 Bean 生命周期
Constructor > @PostConstruct > InitializingBean > init-method
spring中InitializingBean接口使用理解
[推荐-写的简单清晰]spring中InitializingBean接口使用理解
参考URL: https://www.cnblogs.com/study-everyday/p/6257127.html
spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法。
在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。
总结
1:spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用
2:实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖
3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。
思路二:Spring支持set方法注入,可以利用非静态的setter方法注入静态常量。
网上demo
注意:@Value必须修饰在方法上,且set方法不能有static
@Component
public class PropUtil {
private static String NO_ACCESS_URL;
public static String getNO_ACCESS_URL() {
return NO_ACCESS_URL;
}
@Value("${brigade.url.noaccess}")
public void setNO_ACCESS_URL(String NO_ACCESS_URL) {
this.NO_ACCESS_URL = NO_ACCESS_URL;
}
}
前面两种思路总结
上面两种方法,经过测试都是只能,把配置文件读到静态成员变量中,要想读到静态常量不可行。
不行的本质就是 final变量,初始化的的时候就要赋值,final变量的初始化是非常靠前的。
static final修饰的变量又为什么必须在定义的时候进行初始化呢?
首先要明白一点:
final修饰的变量表示赋值之后不能再进行更改,系统赋默认值也算赋值,因此系统也不会赋默认值。
如果不在定义的时候或者构造函数中对final变量进行赋值的话,则生成的对象中final变量的值是未知的(编译器也会直接报错),因此必须进行初始化。
如果用static final同时修饰变量的话,则变量必须在定义的时候进行初始化。因为static变量属于类,在调用构造函数之前就已经被系统赋予默认值了。
如果不在定义的时候初始化,那么既无法在构造函数中初始化,系统也不会赋默认值。则该变量被定义出来是毫无意义的。
思路三: 定义常量时通过前面思路获取的静态成员变量直接赋值初始化
读取spring的配置来定义常量
参考URL: https://blog.csdn.net/tel17666116556/article/details/77045377
问题分析
1、常量定义原则:要用final和static修饰,定义时要初始化,初始化的时候不能通过调用方法的方式。
2、此工具类在使用的时候,须先从spring容器中获取。
思路:先定义一个类,通过setter注入的方式获取spring中的配置信息,并将其定义为静态属性,然后定义常量类,把静态属性赋值给常量
网上demo
public class PropertiesConstants {
/**
* 在线资源地址
* online-resource-path
*/
public static final String ONLINE_RESOURCE_PATH = PropertiesConstantsHelper.onlineResourcePath;
}
/**
* 此类是将spring配置信息转换成静态属性
*/
@Component
class PropertiesConstantsHelper {
static String onlineResourcePath;
@Autowired
public void setUploadProperties(UploadProperties uploadProperties) {
onlineResourcePath = uploadProperties.getOnlineResourcePath();
}
}