FAQ SpringConsultez toutes les FAQ

Nombre d'auteurs : 5, nombre de questions : 41, dernière mise à jour : 24 avril 2008  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de http://www.developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.


SommaireBases de Spring (17)
précédent sommaire suivant
 

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 :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
<?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 :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
<?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 :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
  // 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 :

Code java : Sélectionner tout
1
2
3
MonBean bean = (MonBean )ap.getBean("monBean"); 
// ou 
MonBean bean2 = (MonBean) factory.getBean("monBean");

Mis à jour le 9 septembre 2007 Hikage

La définition d'un bean dans le fichier de configuration se fait comme ceci :

Code xml : Sélectionner tout
1
2
3
<beans> 
<bean id="monBean" class="com.developpez.spring.MonBean"/> 
</beans>

Mis à jour le 27 juin 2007 Hikage

Il est possible de donner plusieurs noms à un Bean via l'attribut name, par exemple le bean :

Code xml : Sélectionner tout
1
2
3
4
5
<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éfini par l'ID), mais aussi monBeanAlias et aliasMonBean. Les différents noms étant séparés par une virgule.

Mis à jour le 27 juin 2007 Hikage

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 :

Code xml : Sélectionner tout
1
2
3
<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é :

Code java : Sélectionner tout
1
2
3
4
5
6
7
<!-- 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>

Mis à jour le 27 juin 2007 Hikage

Spring fournit des balises afin de pouvoir gérer facilement les propriétés de type Properties :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
<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 :

Code : Sélectionner tout
1
2
3
application.nom=Mon Application 
application.version=1.0.0 
application.auteur=Gildas Cuisinier

Mis à jour le 27 juin 2007 Hikage

Afin d'illustrer l'injection de Bean dans un autre grâce à Spring partons d'un exemple.

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

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
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 :

Code java : Sélectionner tout
1
2
3
public interface UserDao { 
    public List listUsers(); 
}
Et une implémentation de cette interface :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
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 :

Code xml : Sélectionner tout
  <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é :

Code xml : Sélectionner tout
1
2
3
<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.

Mis à jour le 9 septembre 2007 Hikage

Pour injecter des propriétés via le constructeur d'une classe, il faut utiliser les balises constructor-arg.

Soit la classe :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
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 :

Code xml : Sélectionner tout
1
2
3
4
<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 :

Code java : Sélectionner tout
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 :

Code xml : Sélectionner tout
1
2
3
4
<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>

Mis à jour le 9 août 2007 Hikage

Soit un fichier properties qui contient les informations suivantes :

Code : Sélectionner tout
1
2
3
4
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 :

Code xml : Sélectionner tout
1
2
3
4
5
<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 ${ } :

Code xml : Sélectionner tout
1
2
3
4
5
6
<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>

Mis à jour le 8 août 2007 Hikage

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é dans une classe Constants :

Code java : Sélectionner tout
1
2
3
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 :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
 <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 raccourci pour faire la même opération :

Code xml : Sélectionner tout
1
2
3
4
5
<bean id="applicationInformationV2" class="com.developpez.spring.ApplicationInformation"> 
        <property name="applicationName"> 
          <util:constant static-field="com.developpez.spring.Constants.APPLICATION_NAME"/> 
        </property> 
    </bean>

Mis à jour le 8 août 2007 Hikage

Soit la classe :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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 :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
<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>

Mis à jour le 27 juin 2007 Hikage

Soit la classe :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
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 :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
<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>

Mis à jour le 8 août 2007 Hikage

Soit une classe :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
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 :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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 :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
<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>

Mis à jour le 8 août 2007 Hikage

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 que celui-ci implémente une de ces deux interfaces pour que Spring injecte automatiquement la référence correspondante :

Code java : Sélectionner tout
1
2
3
4
5
6
7
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; 
}

Mis à jour le 8 août 2007 Hikage

Dans le cas de l'injection de dépendances 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 :

Code xml : Sélectionner tout
1
2
3
4
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’existence de tous les paramètres ainsi que leur validité, ou encore de configurer certaines ressources manuellement.

Mis à jour le 8 août 2007 Hikage

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.

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ApplicationContextHolder implements ApplicationContextAware { 
  
	/** Contexte Spring qui sera injecté par Spring directement */ 
	private static ApplicationContext context = null; 
  
  
	/** 
	* Méthode de ApplicationContextAware, qui sera appelée automatiquement par le conteneur 
	*/ 
	public void setApplicationContext(ApplicationContext ctx) 
			throws BeansException { 
		context = ctx; 
	} 
  
  
	/** 
	 * Méthode 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 :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
<?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 :

Code java : Sélectionner tout
1
2
ApplicationContext context = ApplicationContextHolder.getContext(); 
MonBean bean = (MonBean) context.getBean("monBean");

Mis à jour le 24 avril 2008 Hikage Righetto Dominique

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 :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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é :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
<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.

Mis à jour le 24 avril 2008 Hikage

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.

Code java : Sélectionner tout
1
2
3
4
ConfigurableApplicationContext context = new ClasspathApplicationContext("com/developpez/hikage/context/applicationContext.xml"); 
  
// Termine le contexte Spring 
context.close();
Attentioncependant, seuls 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.

Mis à jour le 24 avril 2008 djo.mos

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

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 © 2017 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 Spring : Mickael Baron - Robin56 -