Вопрос по configuration, java, spring, app-config – Как заставить пружину ввести значение в статическое поле

66

Я знаю, что это может выглядеть как ранее заданный вопрос, но здесь я сталкиваюсь с другой проблемой.

У меня есть служебный класс, который имеет только статические методы. Я не делаю, и я не буду брать пример из этого.

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

    }

    public static void methodB(){

    }
}

Теперь мне нужно Spring, чтобы заполнить 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-компонентом, ничего не изменится, я все равно не смогу использовать переменную, поскольку экземпляр класса не будет создан, а переменная всегда равна ноль.

Ваш Ответ

2   ответа
105

non-static setter for static property/field; using org.springframework.beans.factory.config.MethodInvokingFactoryBean to invoke a static setter.

В первом варианте у вас есть компонент с обычным установщиком, но вместо этого вы устанавливаете свойство экземпляра, вы устанавливаете статическое свойство / поле.

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

но для того, чтобы сделать это, вам нужен экземпляр bean-компонента, который будет выставлять этот установщик (это больше похоже наworkaround).

Во втором случае это будет сделано следующим образом:

<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
staticMethod является собственностьюMethodInvokingFactoryBean и настроен с полным именем статического метода, желание будет вызываться с аргументами, предоставленными свойствуargument.
Я не пробовал 1-е решение, так как плохо его понимал. Я попробовал 2-е решение, и оно работало отлично. Osama Felfel
21

мне нужно было вставить bean-компонент, управляемый Spring, в мой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 construction time, это@Configuration получает все те бины, которые мне нужно вставить как статические поля в другие классы. Затем с@PostConstruct аннотации, я ловлю хук, чтобы сделать всю логику внедрения статического поля.

@Configuration
public class StaticFieldInjectionConfiguration {

    @Inject
    private PersonRepository personRepository;

    @PostConstruct
    private void init() {
        Person.setPersonRepository(personRepository);
    }
}
Мне интересно, как кто-то ссылается на статическую переменную через «это»? в статическом контексте?
@JonasGeiregat это возможно, поскольку метод является статическим, и он обращается к статической переменной
Как это возможно, вы можете получить доступ к этому статическим методом? Я не верю, что это вообще возможно! Разве это не должно быть Person.personRepository = personRepository?
Это работает, но это плохая практика, и она такая же, как если бы вы использовали имя класса вместо этого. Eclipes отметит это предупреждением.

Похожие вопросы