文章目录

  • spring初始化配置文件到常量类
  • 思路一:Spring中的InitializingBean
  • spring中InitializingBean接口使用理解
  • 思路二:Spring支持set方法注入,可以利用非静态的setter方法注入静态常量。
  • 前面两种思路总结
  • 思路三: 定义常量时通过前面思路获取的静态成员变量直接赋值初始化


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:

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:

问题分析
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();
    }
}