如何使弹簧注入值进入静态场


68

我知道这看起来像是一个先前提出的问题,但是我在这里面临另一个问题。

我有一个只有静态方法的实用程序类。我不会,也不会从中获得实例。

public class Utils{
    private static Properties dataBaseAttr;
    public static void methodA(){

    }

    public static void methodB(){

    }
}

现在我需要Spring用数据库属性Properties填充dataBaseAttr.Spring的配置是:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

<util:properties id="dataBaseAttr"
        location="file:#{classPathVariable.path}/dataBaseAttr.properties" />
</beans>

我已经在其他bean中做到了,但是此类(Utils)中的问题不是bean,如果我将其变成bean,则没有任何变化,但我仍然无法使用变量,因为该类不会被实例化并且总是变量等于null。

Answers:


110

您有两种可能性:

  1. 静态属性/字段的非静态设置器;
  2. 通过org.springframework.beans.factory.config.MethodInvokingFactoryBean调用静态的制定者。

在第一个选项中,您有一个带有常规setter的bean,但设置实例属性的是设置静态属性/字段。

public void setTheProperty(Object value) {
    foo.bar.Class.STATIC_VALUE = value;
}

但是为了做到这一点,您需要有一个将实例化此setter的bean实例(它更像是一种变通方法)。

在第二种情况下,将执行以下操作:

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="foo.bar.Class.setTheProperty"/>
    <property name="arguments">
        <list>
            <ref bean="theProperty"/>
        </list>
   </property>
</bean>

根据您的情况,您将在Utils课程上添加一个新的二传手:

public static setDataBaseAttr(Properties p)

并且在您的上下文中,您将使用上述示例性方法对其进行配置,大致类似:

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="foo.bar.Utils.setDataBaseAttr"/>
    <property name="arguments">
        <list>
            <ref bean="dataBaseAttr"/>
        </list>
   </property>
</bean>

非常感谢,您真的挽救了我的一天。
Osama FelFel 2012年

我不太了解第一种解决方案,所以没有尝试。我尝试了第二种解决方案,效果很好。
Osama FelFel 2012年

5
绝对比第一个更喜欢这些选择中的第二个。每次创建实例时设置静态字段都是一个很奇怪的模式。
帕特里克

您还可以像这样发送一个简单的属性:<property name =“ arguments” value =“ 4096” />
Paul Gregoire 2014年

1
staticMethod是的属性,MethodInvokingFactoryBean并使用完全限定的静态方法名称进行配置,wish将使用提供给该属性的参数进行调用argument
Francisco Spaeth 2015年

22

我有一个类似的要求:我需要将Spring管理的存储库bean注入我的Person实体类(“实体”,如“带有身份的事物”,例如JPA实体)。一个Person实例有朋友,并且为了Person返回它的朋友,它应该委托给它的存储库并在那里查询朋友。

@Entity
public class Person {
    private static PersonRepository personRepository;

    @Id
    @GeneratedValue
    private long id;

    public static void setPersonRepository(PersonRepository personRepository){
        this.personRepository = personRepository;
    }

    public Set<Person> getFriends(){
        return personRepository.getFriends(id);
    }

    ...
}

@Repository
public class PersonRepository {

    public Person get Person(long id) {
        // do database-related stuff
    }

    public Set<Person> getFriends(long id) {
        // do database-related stuff
    }

    ...
}

那么如何将那个PersonRepository单例注入到类的静态字段中Person呢?

我创建了一个@Configuration,在Spring ApplicationContext构建时获取了它。这@Configuration将注入我需要作为静态字段注入其他类的所有那些bean。然后,通过@PostConstruct注释,我抓住了一个钩子来执行所有静态场注入逻辑。

@Configuration
public class StaticFieldInjectionConfiguration {

    @Inject
    private PersonRepository personRepository;

    @PostConstruct
    private void init() {
        Person.setPersonRepository(personRepository);
    }
}

1
您怎么可能从静态方法访问它呢?我完全不相信这是可能的!不应该是Person.personRepository = personRepository吗?
乔纳斯·吉雷加特

3
@JonasGeiregat是可能的,因为该方法是静态的,并且正在访问静态变量
Anuj Acharya

4
我想知道有人在静态上下文中通过“ this”引用静态变量吗?
Kripz '16

它可以工作,但这是一种不好的做法,就像您将使用类名来代替它一样。Eclipes会用警告标记它。
卡尼

您可以通过构造函数注入来完成此操作,然后不需要该字段或
postconstruct

1

由于这些答案很旧,因此我找到了替代方法。它非常干净,并且仅适用于Java批注:

要解决此问题,请创建一个“无静态设置器”以为静态变量分配注入值。例如 :

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

@Component
public class GlobalValue {

public static String DATABASE;

@Value("${mongodb.db}")
public void setDatabase(String db) {
    DATABASE = db;
}
}

https://www.mkyong.com/spring/spring-inject-a-value-into-static-variables/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.