Configuration avancée des beans Spring : portée, injection de collections, autowiring et cycle de vie

Définir la portée d’un bean

Spring propose plusieurs stratégies d’instancaition. Les plus courantes sont :

  • singleton : une seule instance partagée (comportement par défaut)
  • prtootype : une nouvelle instance à chaque demande
<bean id="compteService" class="demo.service.CompteService" scope="prototype">
    <property name="compteRepo" ref="compteRepo"/>
</bean>
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
CompteService c1 = ctx.getBean("compteService", CompteService.class);
CompteService c2 = ctx.getBean("compteService", CompteService.class);
System.out.println(c1 == c2); // false

Injection de collections

Supposons un repository capable de recevoir des paramètres de configuration sous forme de collections :

package demo.repo;

import java.util.*;

public class CompteRepo {
    private Set<String> blacklist;
    private List<Integer> priorites;
    private Map<String, String> mapping;

    // setters & getters omis
    @Override
    public String toString() {
        return blacklist.size() + "|" + priorites.size() + "|" + mapping.size();
    }
}

Configuration XML :

<bean id="compteRepo" class="demo.repo.CompteRepo">
    <property name="blacklist">
        <set>
            <value>spam@example.com</value>
        </set>
    </property>
    <property name="priorites">
        <list>
            <value>1</value>
            <value>2</value>
        </list>
    </property>
    <property name="mapping">
        <map>
            <entry key="EUR" value="€"/>
            <entry key="USD" value="$"/>
            <entry key="JPY" value="¥"/>
        </map>
    </property>
</bean>
CompteRepo repo = ctx.getBean("compteRepo", CompteRepo.class);
System.out.println(repo); // 1|2|3

Autowiring automatique

L’attribut autowire accepte plusieurs modes :

  • byName : correspondance par nom de propriété
  • byType : correspondance par type
  • constructor : injection via le constructeur
  • no : désactivation
package demo.repo;

public class CompteRepo {
    private int version;
    // setters & getters
    public String toString() { return "v" + version; }
}
<bean id="compteRepo" class="demo.repo.CompteRepo">
    <property name="version" value="1"/>
</bean>
<bean id="compteRepoBeta" class="demo.repo.CompteRepo">
    <property name="version" value="2"/>
</bean>

<bean id="compteService" class="demo.service.CompteService"
      autowire="byName"/>

Spring injectera le bean nommé compteRepo dans la propriété compteRepo de CompteService.

Pour éviter la répétition, on peut déclarer default-autowire="byName" sur l’élément racine <beans>.

Gestion du cycle de vie

Initialisation différée

Ajouter lazy-init="true" retarde la création du bean jusqu’à sa première utilisation.

<bean id="lourdService" class="demo.service.LourdService" lazy-init="true"/>

On peut aussi activer le comportement par défaut :

<beans default-lazy-init="true"> ... </beans>

Callbacks personnalisés

Les attributs init-method et destroy-method désignent les méthodes à invoquer après la création et avant la destruction.

package demo.service;

public class CompteService {
    public void demarrer() {
        System.out.println("Service démarré");
    }
    public void arreter() {
        System.out.println("Service arrêté");
    }
}
<bean id="compteService" class="demo.service.CompteService"
      init-method="demarrer" destroy-method="arreter">
    <property name="compteRepo" ref="compteRepo"/>
</bean>
ClassPathXmlApplicationContext ctx =
        new ClassPathXmlApplicationContext("beans.xml");
CompteService service = ctx.getBean(CompteService.class);
ctx.close(); // déclenche la méthode arreter()

Note : pour les beans de portée prototype, Spring ne gère pas la destruction ; la responsabilité revient au code client.

Étiquettes: Spring Framework IoC Container bean scope collection injection autowiring

Publié le 26 août à 08h07