Spring:如何向静态字段注入值?

Posted

技术标签:

【中文标题】Spring:如何向静态字段注入值?【英文标题】:Spring: How to inject a value to static field? 【发布时间】:2011-08-31 07:12:05 【问题描述】:

有了这个类

@Component
public class Sample 

    @Value("$my.name")
    public static String name;



如果我尝试Sample.name,它总是'null'。所以我尝试了这个。

public class Sample 

    public static String name;

    @PostConstruct
    public void init()
        name = privateName;
    

    @Value("$my.name")
    private String privateName;

    public String getPrivateName() 
        return privateName;
    

    public void setPrivateName(String privateName) 
        this.privateName = privateName;
      


此代码有效。 Sample.name 设置正确。这是好方法还是不好?如果没有,有没有更好的方法?又该怎么做呢?

【问题讨论】:

这不会解决;如果在对象创建之前使用静态变量。例如)如果在静态块下使用静态变量来构造资源,那么资源将被构造为null。 【参考方案1】:

首先,public staticfinal 字段是邪恶的。 Spring 不允许注入这些字段是有原因的。

您的解决方法 是有效的,您甚至不需要 getter/setter,private 字段就足够了。另一方面,试试这个:

@Value("$my.name")
public void setPrivateName(String privateName) 
    Sample.name = privateName;
  

(适用于@Autowired/@Resource)。但是给你一些建设性的建议:用private 字段和getter 创建第二个类,而不是public static 字段。

【讨论】:

对于“public static non-final fields are evil”,你能给我一些参考吗? 非最终意味着您可以修改字段值,对于静态字段,这意味着处理线程并发 - 也就是堆栈中的痛苦。 如何在静态块中使用@Value?请指导我们...问候,内哈 仅供参考:上面的代码将导致 Sonar / Checkstyle 违规(如果您对这种事情感到困扰),因为您有一个写入静态字段的实例方法。 可以通过使用静态设置器来模仿最终方面,该设置器仅在当前为空时设置值。因此,您只允许对该字段进行一次修改。 (这当然是私有的,并使用吸气剂来访问它)。 Spring 可以在其配置阶段(XML 或 Annotation)调用静态方法。【参考方案2】:

此信息的来源是:https://www.baeldung.com/spring-inject-static-field

Spring 在找到 @Value 注解时使用依赖注入来填充特定的值。但是,不是将值传递给实例变量,而是将其传递给隐式 setter。然后这个 setter 处理我们的 NAME_STATIC 值的填充。

    @RestController 
//or if you want to declare some specific use of the properties file then use
//@Configuration
//@PropertySource("classpath:application-$youeEnvironment.properties")
public class PropertyController 
 
    @Value("$name")//not necessary
    private String name;//not necessary
 
    private static String NAME_STATIC;
 
    @Value("$name")
    public void setNameStatic(String name)
        PropertyController.NAME_STATIC = name;
    

【讨论】:

【参考方案3】:

这是我加载静态变量的示例代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class OnelinkConfig 
    public static int MODULE_CODE;
    public static int DEFAULT_PAGE;
    public static int DEFAULT_SIZE;

    @Autowired
    public void loadOnelinkConfig(@Value("$onelink.config.exception.module.code") int code,
            @Value("$onelink.config.default.page") int page, @Value("$onelink.config.default.size") int size) 
        MODULE_CODE = code;
        DEFAULT_PAGE = page;
        DEFAULT_SIZE = size;
    

【讨论】:

【参考方案4】:

如果想在Spring Boot应用的主类中使用ApplicationContext,可以直接使用SpringApplication.run的返回值。

【讨论】:

【参考方案5】:

虽然可能需要实施变通方法,但在大多数情况下应尽量避免使用它们。 Spring 擅长处理依赖注入并将大多数对象视为单例。这意味着 Spring 可以为您处理对象的创建,以及在运行时注入这些对象。当将此与您的 Spring 托管 bean 可能是 Singleton 的事实结合起来时,静态方法和变量的使用在很大程度上是不必要的。您可以简单地在构造函数级别或变量级别自动装配您要查找的对象的实例,并引用方法或变量的非静态版本。这是理想的,其行为类似于静态引用。非静态变量基本上是静态的,因为您只在代码的每一部分中使用对象的一个​​实例,并且由于依赖注入,您永远不会处理对象的实例化,就像使用静态引用一样!伟大的!现在我确定在某些情况下您需要解决方法(即您没有使用依赖注入或类不是单例),但如果可能的话尽量不要使用解决方法。这也只是我的 2 美分。有人可能会提供 3 个。(:

public class InjectableClass
     @Value("$my.value")
     private String myString;
    
     public String nonStaticMethod()
           return myString;
     


public class LogicClass
    private InjectableClass injectableClass;
    @Autowire
    public LogicClass(InjectableClass injectableClass)
       this.injectableClass = injectableClass;
    

    public void logicClassMethod()
        System.out.println("Hey! Here is the value I set on myString: " + 
                         injectableClass.nonStaticMethod() + ". That was 
                          basically like using a static method!");
    
 

【讨论】:

以上是关于Spring:如何向静态字段注入值?的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring 中为静态常量注入值

Spring-如何给静态变量注入值

如何使弹簧将值注入静态字段

spring 读取配置文件,将值注入到静态字段

Spring如何通过XML向队列注入值

spring 项目中在类中注入静态字段