web-dev-qa-db-fra.com

Comment faire pour que le ressort injecte de la valeur dans un champ statique

Je sais que cela peut ressembler à une question posée précédemment, mais je suis confronté à un problème différent ici.

J'ai une classe utilitaire qui n'a que des méthodes statiques. Je ne le sais pas et je ne vais pas en prendre exemple.

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

    }

    public static void methodB(){

    }
}

Maintenant, j'ai besoin de Spring pour remplir dataBaseAttr avec les attributs de base de données Properties.Spring config est:

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

Je l'ai déjà fait dans d'autres haricots mais le problème ici dans cette classe (Utils) n'est pas un haricot. Et si j'en fais un haricot, rien ne change, je ne peux toujours pas utiliser la variable car la classe ne sera pas instanciée et toujours variable est égal à zéro.

67
Osama FelFel

Vous avez deux possibilités:

  1. setter non statique pour la propriété/le champ statique;
  2. en utilisant org.springframework.beans.factory.config.MethodInvokingFactoryBean pour appeler un séparateur statique.

Dans la première option, vous avez un bean avec un setter standard, mais définissez plutôt une propriété d'instance, vous définissez la propriété/le champ static.

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

mais pour ce faire, vous devez avoir une instance d'un bean qui exposera ce programme de configuration (il s'agit plutôt d'une solution de contournement ).

Dans le second cas, cela se ferait comme suit:

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

Dans votre cas, vous allez ajouter un nouveau paramètre dans la classe Utils:

public static setDataBaseAttr(Properties p)

et dans votre contexte, vous le configurerez avec l'approche décrite ci-dessus, plus ou moins comme:

<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>
105
Francisco Spaeth

J'ai eu une exigence similaire: je devais injecter un bean de référentiel géré par Spring dans ma classe d'entités Person ("entity" comme dans "quelque chose avec une identité", par exemple une entité JPA). Une instance Person a des amis, et pour que cette instance Person renvoie ses amis, elle doit déléguer à son référentiel et y rechercher des amis.

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

    ...
}

Alors, comment ai-je injecté ce singleton PersonRepository dans le champ statique de la classe Person?

J'ai créé un @Configuration, qui est récupéré à temps de construction Spring ApplicationContext. Cette @Configuration reçoit tous les haricots que je dois injecter sous forme de champs statiques dans d’autres classes. Puis avec un @PostConstruct annotation, j'attrape un crochet pour faire toute la logique d'injection de champ statique.

@Configuration
public class StaticFieldInjectionConfiguration {

    @Inject
    private PersonRepository personRepository;

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