Wie man den Federeinspritzwert in ein statisches Feld bringt

68

Ich weiß, dass dies wie eine zuvor gestellte Frage aussieht, aber ich stehe hier vor einem anderen Problem.

Ich habe eine Utility-Klasse, die nur statische Methoden hat. Ich nicht und ich werde keine Instanz daraus nehmen.

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

    }

    public static void methodB(){

    }
}

Jetzt brauche ich Spring, um dataBaseAttr mit Datenbankattributen zu füllen. Properties.Spring config is:

<?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>

Ich habe es bereits in anderen Beans gemacht, aber das Problem hier in dieser Klasse (Utils) ist keine Bean. Und wenn ich es zu einer Bean mache, ändert sich nichts. Ich kann die Variable immer noch nicht verwenden, da die Klasse nicht immer instanziiert und variabel ist gleich null.

Osama FelFel
quelle

Antworten:

109

Sie haben zwei Möglichkeiten:

  1. nicht statischer Setter für statische Eigenschaft / Feld;
  2. Verwenden Sie org.springframework.beans.factory.config.MethodInvokingFactoryBean, um einen statischen Setter aufzurufen.

In der ersten Option haben Sie eine Bean mit einem regulären Setter, aber stattdessen setzen Sie eine Instanzeigenschaft, die Sie als statische Eigenschaft / Feld festlegen.

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

Um dies zu tun, benötigen Sie jedoch eine Instanz einer Bean, die diesen Setter verfügbar macht (es ist eher eine Problemumgehung ).

Im zweiten Fall würde es wie folgt gemacht:

<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>

In Ihrem Fall fügen Sie der UtilsKlasse einen neuen Setter hinzu :

public static setDataBaseAttr(Properties p)

und in Ihrem Kontext konfigurieren Sie es mit dem oben beispielhaften Ansatz, mehr oder weniger wie folgt:

<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>
Francisco Spaeth
quelle
Vielen Dank, du hast meinen Tag wirklich gerettet.
Osama FelFel
Ich habe die erste Lösung nicht ausprobiert, da ich sie nicht gut verstanden habe. Ich habe die 2. Lösung ausprobiert und es hat super funktioniert.
Osama FelFel
5
Ziehen Sie auf jeden Fall die zweite dieser Optionen der ersten vor. Das Festlegen statischer Felder bei jeder Erstellung einer Instanz ist ein wirklich seltsames Muster.
Patrick
Sie können auch einfach eine einfache Eigenschaft wie folgt senden: <property name = "arguments" value = "4096" />
Paul Gregoire
1
staticMethodist eine Eigenschaft von MethodInvokingFactoryBeanund wird mit dem vollständig qualifizierten statischen Methodennamen konfiguriert. Der Wunsch wird mit den für die Eigenschaft angegebenen Argumenten aufgerufen argument.
Francisco Spaeth
22

Ich hatte eine ähnliche Anforderung: Ich musste eine von Spring verwaltete Repository-Bean in meine PersonEntitätsklasse einfügen ("Entität" wie in "Etwas mit einer Identität", zum Beispiel eine JPA-Entität). Eine PersonInstanz hat Freunde, und damit diese PersonInstanz ihre Freunde zurückgibt, delegiert sie an ihr Repository und fragt dort nach Freunden ab.

@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
    }

    ...
}

Wie habe ich diesen PersonRepositorySingleton in das statische Feld der PersonKlasse eingefügt ?

Ich habe eine erstellt @Configuration, die zur Erstellungszeit von Spring ApplicationContext abgeholt wird . Dies @Configurationwird mit all den Beans injiziert, die ich als statische Felder in andere Klassen injizieren muss. Dann @PostConstructfange ich mit einer Anmerkung einen Haken, um die gesamte Logik der statischen Feldinjektion auszuführen.

@Configuration
public class StaticFieldInjectionConfiguration {

    @Inject
    private PersonRepository personRepository;

    @PostConstruct
    private void init() {
        Person.setPersonRepository(personRepository);
    }
}
Abdull
quelle
1
Wie ist es möglich, dass Sie über eine statische Methode darauf zugreifen können? Ich glaube nicht, dass das überhaupt möglich ist! Sollte es nicht Person.personRepository = personRepository sein?
Jonas Geiregat
3
@ JonasGeiregat es ist möglich, da die Methode statisch ist und auf statische Variable zugreift
Anuj Acharya
4
Ich frage mich, wie jemand eine statische Variable durch "dies" in einem statischen Kontext referenziert.
Kripz
Es funktioniert, aber es ist eine schlechte Praxis und es ist das gleiche, als würden Sie stattdessen den Klassennamen verwenden. Eclipes würde es mit einer Warnung markieren.
Kani
Sie hätten dies mit einer Konstruktorinjektion tun können und würden dann weder das Feld noch die
Nachkonstruktionsmethode
1

Da diese Antworten alt sind, habe ich diese Alternative gefunden. Es ist sehr sauber und funktioniert nur mit Java-Anmerkungen:

Um dies zu beheben, erstellen Sie einen "nicht statischen Setter", um den injizierten Wert für die statische Variable zuzuweisen. Zum Beispiel :

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/

Carlos Andres
quelle