Developpez.com - Java
X

Choisissez d'abord la catégorieensuite la rubrique :

logo
Sommaire > Bases de Spring
        Comment configurer et utiliser un conteneur Spring ?
        Comment définir un bean ?
        Comment définir plusieurs noms pour un Bean
        Comment définir un Bean en tant que singleton ?
        Comment injecter des propriétés de type Properties
        Comment injecter un Bean dans un autre ?
        Comment injecter des dépendances via le constructeur ?
        Comment externaliser des propriétés dans un fichier Properties ?
        Comment injecter une constante statique dans une propriété?
        Comment injecter des propriétés de types simples ?
        Comment configurer une liste ?
        Comment configurer une Map ?
        Comment fournir le context Spring à un Bean ?
        Comment effectuer des vérifications après la configuration des propriétés?
        Comment accéder au contexte Spring depuis un composant non géré par Spring ?
        Que propose le namespace p
        Comment fermer un contexte d'application en détruisant les Beans ?

rechercher
precedent    sommaire    suivant    telechargermiroir


Comment configurer et utiliser un conteneur Spring ?
auteur : Gildas Cuisinier
Afin de configurer un conteneur Spring, il est nécessaire de créer un fichier xml contenant la définition des divers Beans qui seront gérés par Spring.

Voici un exemple simple de ce fichier, version Spring 2.0 utilisant des namespaces :

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

	<bean name="unBean" class="com.developpez.spring.unBean">
        <property name="unePropriete" value="Hello world"/>
	</bean>	
</beans>
Le même fichier, mais pour Spring 1.2 qui utilise une DTD à la place des namespaces :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean name="unBean" class="com.developpez.spring.unBean">
        <property name="unePropriete" value="Hello world"/>
	</bean>	
</beans>
Une fois le fichier créé, il est nécessaire d'instancier une fabrique de Beans ( Bean Factory ) ou un contexte d'application ( ApplicationContext ). Il existe diverses implémentations de ces interfaces, mais les deux principales chargent un ( ou plusieurs ) fichier situé soit par un chemin sur le disque, soit dans le classpath :

  // Instanciation d'un contexte Spring à partir d'un fichier XML dans le classpath
        ApplicationContext ap = new ClassPathXmlApplicationContext("com/developpez/spring/applicationContext.xml");

        // Instanciation d'un contexte Spring à partir d'un fichier sur le disque
        ApplicationContext ap2 = new FileSystemXmlApplicationContext("c:\\applicationContext.xml");

        // Instanciation d'un BeanFactory à partir d'un fichier xml dans le classpath
        Resource resource = new ClassPathResource("com/developpez/spring/beans.xml");
        BeanFactory factory = new XmlBeanFactory(resource);

    // Instanciation d'un BeanFactory à partir d'un fichier xml sur le disque
        Resource resource2 = new FileSystemResource("c:\\beans.xml");
        BeanFactory factory2 = new XmlBeanFactory(resource);
Une fois une instance créée, la récupération d'un Bean Spring se fait via la méthode getBean :

MonBean bean = (MonBean )ap.getBean("monBean");
// ou
MonBean bean2 = (MonBean) factory.getBean("monBean");
lien : Documentation officiel de Spring - Fabrique de Beans

Comment définir un bean ?
auteur : Gildas Cuisinier
La définition d'un bean dans le fichier de configuration se fait comme ceci :
<beans>
<bean id="monBean" class="com.developpez.spring.MonBean"/>
</beans>

Comment définir plusieurs noms pour un Bean
auteur : Gildas Cuisinier

Il est possible de donner plusieurs noms à un Bean via l'attribut name, par exemple le bean :
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    <bean id="monBean" class="com.developpez.spring.MonBean" name="monBeanAlias,aliasMonBean" />
</beans>

possède le nom monBean ( définit par l'ID ) mais aussi monBeanAlias et aliasMonBean. Les différents noms étant séparés par une virgule


Comment définir un Bean en tant que singleton ?
auteur : Gildas Cuisinier
Si rien n'est spécifié, Spring considère tout Bean comme un singleton. Autrement dit, lorsque deux demandes sont faites pour un même Bean, c'est la même instance de l'objet qui est fournie par le BeanFactory/ApplicationContext.

Si vous désirez qu'un nouvel objet soit instancié à chaque fois il faut le spécifier dans la définition du Bean :

<beans>
<bean id="monBean" class="com.developpez.spring.MonBean" singleton="false"/>
</beans>
Depuis la version 2.0 de Spring, c'est via l'attribut Scope que cela est géré :

<!-- Bean Singleton -->
<bean id="monBean" class="com.developpez.spring.MonBean" scope="singleton"/>
</beans>

<!-- Bean non Singleton -->
<bean id="monBean" class="com.developpez.spring.MonBean" scope="prototype"/>
</beans>
lien : en Documentation officielle, Scope

Comment injecter des propriétés de type Properties
auteur : Gildas Cuisinier
Spring fournit des balises afin de pouvoir gérer facilement les propriétés de type Properties :


<bean id="monBean" class="com.developpez.spring.MonBean" name="monBeanAlias,aliasMonBean">
        <property name="proprietes">
            <props>
                <prop key="application.nom">Mon Application</prop>
                <prop key="application.version">1.0.0</prop>
                <prop key="application.auteur">Gildas Cuisinier</prop>
            </props>
        </property>
    </bean>
    
équivaut à un fichier properties :

application.nom=Mon Application
application.version=1.0.0
application.auteur=Gildas Cuisinier


Comment injecter un Bean dans un autre ?
auteur : Gildas Cuisinier
Afin d'illustrer l'injection de Bean dans un autre grâce à Spring partons d'un exemple :

Soit un service, qui possède entre autre une méthode pour lister les utilisateurs :

public class UserService {

    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public List listUsers(){
        return userDao.listUsers();
    }
}
Le service utilise un DAO pour les utilisateurs. Les méthodes de ce DAO sont définies dans une interface :

public interface UserDao {
    public List listUsers();
}
Et une implémentation de cette interface :

public class UserDaoImpl implements UserDao {
    public List listUsers() {

        List result = new ArrayList();

        result.add(new User("hikage", "password"));
        result.add(new User("spring", "spring"));

        return result;
    }
}
Afin de spécifier à Spring d'injecter une référence du DAO au service, il faut déclarer tout d'abord un bean pointant sur l'implémentation du DAO :

  <bean id="userDao" class="com.developpez.spring.UserDaoImpl"/>
Ensuite, dans la déclaration du service en lui-même, il est nécessaire de créer une propriété :

<bean id="userService" class="com.developpez.spring.UserService">
       <property name="userDao" ref="userDao"/>
   </bean>
Dès lors, lorsque l'on récupérera une instance du service, Spring injectera automatiquement une instance de l'implémentation.

lien : en Documentation officielle, References to other beans

Comment injecter des dépendances via le constructeur ?
auteur : Gildas Cuisinier
Pour injecter des propriétés via le constructeur d'une classe, il faut utiliser les balises constructor-arg.

Soit la classe :

public class BeanConstructor {

    private String chaine;
    private Integer entier;

    public BeanConstructor(String chaine, Integer entier) {
        this.chaine = chaine;
        this.entier = entier; 
    }
}
Il est possible de spécifier les arguments via leur index :

<bean id="beanConstructeur2" class="com.developpez.hikage.BeanConstructor">
        <constructor-arg index="0" value="Test"/>
        <constructor-arg index="1" value="23"/>
    </bean>
Cependant, imaginons maintenant que la classe possède un constructeur supplémentaire :

public BeanConstructor(String chaine, String chaine2)
Dans ce cas, il est préférable de spécifier à Spring de quel type sont les paramètres, afin de s'assurer de passer par le bon constructeur :


<bean id="beanConstructeur" class="com.developpez.hikage.BeanConstructor">
        <constructor-arg type="java.lang.String" value="Test"/>
        <constructor-arg type="java.lang.Integer" value="23"/>
    </bean>

Comment externaliser des propriétés dans un fichier Properties ?
auteur : Gildas Cuisinier
Soit un fichier properties qui contient les informations suivantes :

datasource.driver=org.mysql.driver.Driver
datasource.url=jdbc://mysql:localhost/maBase
datasource.username=dbUser
datasource.password=dbPassword
Il est possible de récupérer ces informations sous forme de variables dans le fichier de configuration de Spring en ajoutant un Bean :

<bean name="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <value>classpath:com/developpez/hikage/properties/datasource.properties</value>
            </property>
        </bean>
Ensuite, pour accèder aux variables il suffit de les encadrer dans ${ } :

<bean id="datasource" class="com.developpez.hikage.Datasource">
        <property name="urlConnection" value="${datasource.url}"/>
        <property name="drivers" value="${datasource.drivers}"/>
        <property name="username" value="${datasource.username}"/>
        <property name="password" value="${datasource.password}"/>
    </bean>

Comment injecter une constante statique dans une propriété?
auteur : Gildas Cuisinier
Les informations nécessaires à la configuration sont parfois stockées dans des champs statiques d'une classe ou d'une interface. Spring fournit une classe utilitaire pour récupérer ces informations pour ainsi les injecter dans un bean.

Par exemple, le nom d'une application est stockée dans une classe Constants :

public class Constants {
    public static final String APPLICATION_NAME = "FAQ Spring";
}
La classe FieldRetrievingFactoryBean fournit un moyen d'injecter cette information dans la propriété applicationName de la classe ApplicationInformation :

 <bean id="applicationInformation" class="com.developpez.spring.ApplicationInformation">
        <property name="applicationName">
            <bean class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
                <property name="staticField" value="com.developpez.spring.Constants.APPLICATION_NAME"/>
            </bean>
        </property>
    </bean>
Depuis la version 2.0 de Spring, via le namespace util, il existe un raccouçi pour faire la même opération :

<bean id="applicationInformationV2" class="com.developpez.spring.ApplicationInformation">
        <property name="applicationName">
          <util:constant static-field="com.developpez.spring.Constants.APPLICATION_NAME"/>
        </property>
    </bean>
lien : Documentation officielle de Spring, Schema Utils

Comment injecter des propriétés de types simples ?
auteur : Gildas Cuisinier
Soit la classe :

public class MonBean {

    private String chaine;
    private Integer entier;
    private Long  entierLong;
    private Boolean booleen;
    private Float flottant;
    
public void setChaine(String chaine) { this.chaine = chaine ; }
public String getChaine() { return this.chaine ; }

public void setEntier(Integer entier) { this.entier = entier ; }
public Integer getEntier() { return this.entier ; }

public void setEntierLong(Long entierLong) { this.entierLong = entierLong ; }
public String getEntierLong() { return this.entierLong ; }

public void setBooleen( Boolean booleen ) { this.booleen = booleen ; }
public Boolean getBooleen() { return this.booleen; }

public void setFlottant(Float flottant) { this.flottant = flottant ; }
public Float getFlottant() { return this.flottant } ;

}
Voici un exemple de fichier de configuration qui spécifie les valeurs des types simples :
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
       
<bean id="monBean" class="com.developpez.spring.MonBean">
        <property name="chaine" value="Visitez Developpez.com"/>
        <property name="booleen"  value="true"/>
        <property name="entier" value="10"/>
        <property name="flottant" value="10.3"/>
        <property name="entierLong" value="204"/>
    </bean>
    
</beans>

Comment configurer une liste ?
auteur : Gildas Cuisinier
Soit la classe :

public class BeanList {
    
    private List list;

    public List getList() {
        return list;
    }

    public void setList(List list) {
        this.list = list;
    }
}
Il est possible de définir cette liste via les balises :

<bean id="beanList" class="com.developpez.hikage.BeanList">
        <property name="list">
            <list>
                <value>Valeur 1</value>
                <value>Valeur 2</value>
                <value>Valeur 3</value>
                <ref bean="monBean"/>
            </list>
        </property>
    </bean>

Comment configurer une Map ?
auteur : Gildas Cuisinier
Soit une classe :

public class BeanMap {

    private Map map;

    public Map getMap() {  return map;}

    public void setMap(Map map) {   this.map = map;   }
}
Pour configurer celle-ci via le fichier XML, il faut utiliser les balises :

<bean id="beanMap" class="com.developpez.hikage.BeanMap">
        <property name="map">
			<map>
				<entry>
			            <key><value>Clé de type String</value></key>
			            <value>Valeur associé de type String</value>
			        </entry>
			        <entry>
			        	<!-- Clé de type Object -->
			            <key><ref bean="monBeanCle"></ref></key>
						<!-- Valeur dde type Object -->
			            <ref bean="monBeanValeur"></ref>
			        </entry>
			</map>
        </property>
    </bean>
Il est aussi possible d'écrire ces lignes de manière abrégée :

<bean id="beanMap" class="com.developpez.hikage.BeanMap">
        <property name="map">
            <map>
                <entry key="Ma clé de type String" value="Valeur associée de type String" />
                <entry key-ref="monBean" value-ref="monBean"/>
            </map>
        </property>
    </bean>

Comment fournir le context Spring à un Bean ?
auteur : Gildas Cuisinier
Il est parfois nécessaire à un Bean de possèder une référence à l'ApplicationContext ( ou le BeanFactory ) qui s'occupe de son cycle de vie. Pour cela, il suffit simplement que celui-ci implémente une de ces deux interfaces pour que Spring injecte automatiquement la référence correspondante :

public interface ApplicationContextAware  {   
    void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws org.springframework.beans.BeansException;
}

public interface BeanFactoryAware  {    
    void setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory) throws org.springframework.beans.BeansException;
}
lien : en Javadoc ApplicationContextAware
lien : en Javadoc BeanFactoryAware

Comment effectuer des vérifications après la configuration des propriétés?
auteur : Gildas Cuisinier
Dans le cas de l'injection de dépendance par accesseurs, il n'est pas possible de manière standard de vérifier que tous les arguments obligatoires sont fournis. De plus, il est parfois nécessaire d'effectuer certaines opérations de configuration manuellement. Pour cela, Spring fournit une interface :

public interface InitializingBean  {
    
    void afterPropertiesSet() throws java.lang.Exception;
}
Dès qu'un bean implémente cette interface, Spring appellera la méthode afterPropertiesSet après l'appel de tous les accesseurs, fournissant ainsi un moyen de vérifier l'existance de tous les paramètres ainsi que leur validité, ou encore de configurer certaines ressources manuellement.


Comment accéder au contexte Spring depuis un composant non géré par Spring ?
auteurs : Gildas Cuisinier, Righetto Dominique
Pour donner accès au contexte Spring aux composants non gérés par Spring, il suffit d'implémenter un bean géré par Spring, implémentant ApplicationContextAware, qui va exposer des méthodes d'accès au contexte Spring.

public class ApplicationContextHolder implements ApplicationContextAware {
 
	/** Contexte Spring qui sera injecte par Spring directement */
	private static ApplicationContext context = null;
 

	/**
	* Méthode de ApplicationContextAware, qui sera appellée automatiquement par le conteneur
	*/
	public void setApplicationContext(ApplicationContext ctx)
			throws BeansException {
		context = ctx;
	}
 
 
	/**
	 * Methode statique pour récupérer le contexte
	 */
	public static ApplicationContext getContext() {
		return context;
	}
 
}
Il est ensuite nécessaire de configurer cette classe dans le contexte 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"
	xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
	<!-- ==============================   BEANS   ============================= -->
	<!-- Bean d'acces au Contexte -->
	<bean id="applicationContextHolder"	class="com.developpez.spring.ApplicationContextHolder" />
 
	<!-- Definition des autres beans -->
</beans>
Le principe est que lors de l'instanciation de la classe ApplicationContextHolder par le conteneur Spring, celui-ci va détecter qu'elle implémente l'interface ApplicationContextAware, et donc lui injecter le contexte.
Le setteur de la classe va stocker ce contexte dans une variable de classe ( variable déclarée statique ). Et la classe propose une méthode, statique, de récupération de ce contexte.

Exemple d'utilisation :

ApplicationContext context = ApplicationContextHolder.getContext();
MonBean bean = (MonBean) context.getBean("monBean");
lien : faq Comment fournir le context Spring à un Bean ?

Que propose le namespace p
auteur : Gildas Cuisinier
Le namespace p a pour but de réduire la taille du fichier de configuration de Spring, en proposant des raccourcis pour la définition des propriétés.

Par exemple, un fichier de configuration sans le namespace p :

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
    <bean name="monBean" class="com.developpez.spring.Personne">
        <property name="nom" value="Cuisinier"/>
        <property name="prenom" value="Gildas"/>
        <property name="age" value="23"/>
        <property name="pays" value="Belgique"/>        
        <property name="parrain" ref="beanParrain"/>
    </bean>
    
    <bean name="beanParrain" class="com.developpez.spring.Personne"/>
</beans>
Grâce au namespace p, voici le même fichier de configuration adapté :

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
  <bean name="monBean" class="com.developpez.spring.Personne"
  		p:nom="Cuisinier" p:prenom="Gildas" p:age="23 p:pays="Belgique" p:parrain-ref="beanParrain"/>
    </bean>
    
    <bean name="beanParrain" class="com.developpez.spring.Personne"/>
</beans>
La synthaxe étant p:<propriete> pour les valeurs directes et p:<propriete-ref> pour l'injection d'une référence d'un bean.

téléchargement : Documentation officielle sur le site Spring

Comment fermer un contexte d'application en détruisant les Beans ?
Lors de l'utilisation de Spring en dehors d'un contexte Web, il est intéressant de fermer proprement un contexte d'application, en libérant les ressources et les beans.

La méthode close() de l'interface ConfigurableApplicationContext permet de faire cela. Il faut donc que l'implémentation du contexte d'application Spring implémente cette interface, et heureusement c'est le cas de ClasspathXmlApplicationContext, qui est sans doute la version la plus utilisée.

ConfigurableApplicationContext context = new ClasspathApplicationContext("com/developpez/hikage/context/applicationContext.xml");
 
// Termine le contexte Spring
context.close();
Attention cependant, seul les beans de scope singleton seront détruits.

Une autre méthode de ConfigurableApplicationContext qui peut s'avérer utile est registerShutdownHook(). Cette méthode permet de spécifier à la JVM de fermer automatiquement le contexte Spring lorsque l'application s'arrête.

lien : en Documentation de référence

rechercher
precedent    sommaire    suivant    telechargermiroir

Consultez les autres F.A.Q's


Valid XHTML 1.1!Valid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2004 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Responsables bénévoles de la rubrique Java : Mickael Baron - Robin56 -