Spring @Value静态属性无法注入

342 阅读2分钟

场景

数据库存的是相对路径,服务推送等的host值填充

为了方便采用Spring配置文件@Value注入动态注入

而往往处理这些情况都喜欢封装工具类静态方法调用

配置文件

xxx.host=http:xxxx.com

工具类

@Component
public class XXXUtil {
    @Value("xxx.host")
    private static String XXXXHOST;

    private XXXUtil() {}
    
    public static String getXXXHost() {
     // 方法体省略
    }
}

看起来很简单的一个开发任务,结果一测试发现host值一直未null。

明显就是属性没有注入成功。

调试发现去掉static

private String XXXXHOST

可以!!!

未注入的原因

其实原因很简单,认真思考下就知道原因。

@Value 注解是依赖于属性的set方法进行注入的,而static修饰的属性是类属性,不存在set方法

解决方法

1、set方法手动赋值

利用非静态setter方法注入静态变量, 会在Spring加载的时候进行属性注入

@Component
public class XXXUtil {
    
    private static String XXXXHOST;

    private XXXUtil() {}
    
    @Value("xxx.host")
    public void setHost(String host) {
        XXXUtil.XXXXHOST = host;
    }

   public static String getXXXHost() {
     // 方法体省略
    }
}

2、构造方法赋值

set方法差不多

@Component
public class XXXUtil {
    
    private static String XXXXHOST;

    private XXXUtil() {}
    
    @Value("xxx.host")
    public XXXUtil(String host) {
        XXXUtil.XXXXHOST = host;
    }

    public static String getXXXHost() {
     // 方法体省略
    }
}

3、@PostConstruct

@Component 
public class MyComponent {  
    @Value("${xxx.host}")    
    private static final String CONSTANT_VALUE;     
     *// 省略其他代码*
}
@Configuration
@DependsOn("myComponent")
public class StaticConstantInjectionConfig {

    @Bean
    public MyComponent myComponent() {
        MyComponent myComponent = new MyComponent();
        myComponent.setStaticConstantValue(CONSTANT_VALUE);
        return myComponent;
    }

    // 省略其他代码
}

4、@PostConstruct

Spring 只调用一次用@PostConstruct注释的方法,就在 bean 属性的初始化之后。

@PostConstruct注释的方法 可以有任何访问级别,但不能是静态的

@Component
@Slf4j
public class XXXUtil {
    
    private static String XXXXHOST;

    private XXXUtil() {}
    
    @Value("xxx.host")
    private String hostStr;
    
    @PostConstruct
    public void init(){
        XXXXHOST = hostStr;
    }

    public static String getXXXHost() {
     // 方法体省略
    }
}

5、SpringUtils

不过多写了,更多方法欢迎留言讨论!

总结

@Value注解可以用来对Spring容器中的bean的属性进行注入,它能够被用在属性,构造方法,普通方法上。