octobre
2009
Depuis un moment, j’utilise Spring sans XML en Java SE comme djo-mos l’a presenté avec un ClassPathBeanDefinitionScanner.
Toutes mes classes étaient annotés avec Service, Component, Repository pour être détectés au scan et j’ajoutais aussi directement des beans dans le context. Cela marche très bien, mais on est vite assez limité, par exemple si on veut utiliser AOP, Spring Transaction, …
J’ai donc cherché sur internet une solution et je suis tombé sur une perle : Spring JavaConfig, développé par SpringSource
Cette fois, on remplace le fichier de configuration XML par une classe annnotée avec @Configuration. C’est dans cette classe qu’on va déclarer nos beans.
Voici un exemple de classe :
@ImportXML("classpath:test/datasource-config.xml")
@ComponentScan("test.services")
@AnnotationDrivenTx(transactionManager="txManager")
public class ApplicationConfig {
@Bean
public Bar bar() {
return new Bar();
}
@Bean
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(dataSource());
}
}
Il est intéressant de développer les choses suivantes :
- @Configuration(defaultLazy = Lazy.TRUE) : Toutes les classes de configuration doivent être annotées de cette façon pour être comprises pour comme configuration Spring. On peut spécifier des paramètres de Spring via les attributs de l’annotation, comme par exemple utiliser une initialisation lazy pour la création des beans
- @ImportXML(« classpath:test/datasource-config.xml ») : Permet d’importer le contenu d’un fichier de config XML
- @ComponentScan(« test.services ») : Permet de scanner le contenu du package test.services
- @AnnotationDrivenTx(transactionManager= »txManager ») : Permet d’utiliser Spring transaction avec les annotations et de déclarer le transaction manager.
- @Bean : Permet de déclarer un bean. Le nom de la méthode sera le nom du bean.
On peut ensuite obtenir le contexte de la manière suivante :
JavaConfigApplicationContext context = new JavaConfigApplicationContext(ApplicationConfig.class);
et l’utiliser comme n’importe quel applicationContext habituel
Dans un soucis de modularité, on peut également passer plusieurs classes au constructeur de JavaConfigApplicationContext.
Cette librairie a quelques prérequis :
- Java 5.0 or higher
- Spring 2.5.6 or higher
- AspectJ 1.6.2 or higher
- CGLIB 2.1.3
Cette librairie est disponible en version 1.0.0.M4.
Personnellement, je trouve cette façon de faire très élégante. On peut faire tout ce qu’il y a dans un fichier XML de manière programmatique, pour ceux qui préfère la méthode programmatique, je trouve que c’est très intéressant
Pour plus d’infos, je vous inviter à consulter la page officielle : http://www.springsource.org/javaconfig
12 Commentaires + Ajouter un commentaire
Archives
- novembre 2011
- avril 2010
- mars 2010
- février 2010
- janvier 2010
- décembre 2009
- novembre 2009
- octobre 2009
- septembre 2009
- juillet 2009
- juin 2009
- avril 2009
- mars 2009
- février 2009
- octobre 2008
- septembre 2008
- mars 2008
- février 2008
- janvier 2008
- décembre 2007
- novembre 2007
- octobre 2007
- septembre 2007
- août 2007
- juillet 2007
- juin 2007
- mai 2007
- avril 2007
Catégories
- AMD
- Apple
- Cartes graphiques
- Chrome
- Conception
- Divers
- Eclipse
- English
- Hardware
- Informatique générale
- Intégration continue
- IntelliJ Idea
- Java
- JTheque
- Linux
- Logiciels
- Mes articles
- Mes critiques de livres
- Mes projets
- Microsoft
- Mon serveur perso
- Office 2007
- Open Source
- Outils
- Perso
- PHP
- Processeurs
- Programmation
- Sécurité
- Spring
- Windows Vista
- Windows XP
Salut,
En effet, il serait mieux que tu postes tes questions sur le forum Spring, ce sera plus simple et tu auras plus de réponses
A+
oupss … je crois que l’interpreteur a fait sauté mes balise , il fallait lire
« Dans mon fichier config xml de spring j’avais le code suivant :
bean id= »transactionProxy » abstract= »true »
class= »org.springframework.transaction.interceptor.TransactionProxyFactoryBean »
property name= »transactionManager » ref= »transactionManager »
property name= »transactionAttributes »
props
prop key= »* » PROPAGATION_REQUIRED
props
property
bean »
Salut Batiste
tout d’abord merci pour tes conseils ! je me permets de revenir vers toi car je suis encore une fois dans une impasse (d’ailleurs si tu penses qu’il vaut mieux que je poste mes questions autre part n’hésites à me le dire…)
J’ai bien réussi a mettre en pratique ton tuto. Cependant j’ai (encore :$) une question concernant un bean « transactionProxy »
Dans mon fichier config xml de spring j’avais le code suivant :
PROPAGATION_REQUIRED
Voulant éviter un maximum le xml, dans ma class ApplicationConfigTest l’équivalent de ta classe « ApplicationConfig » (cf la classe complète a la fin de ce poste) j’ai ajouté (sans doute bêtement) le code suivant
@Bean()
public TransactionProxyFactoryBean transactionProxy() {
TransactionProxyFactoryBean transactionProxyFactoryBean = new TransactionProxyFactoryBean();
transactionProxyFactoryBean.setTransactionManager(transactionManager());
Properties properties = new Properties();
properties.put(« * », « PROPAGATION_REQUIRED »);
transactionProxyFactoryBean.setTransactionAttributes(properties);
return transactionProxyFactoryBean;
}
Mais du coup j’ai une exception qui est levée :
« threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘transactionProxy': org.springframework.beans.factory.FactoryBeanNotInitializedException: FactoryBean is not fully initialized yet”
Aurais tu une idée (et la patience :$) de m’expliquer mon erreur ?
En espérant ne pas abuser de ton temps, je te remercie d’avance
@Configuration(defaultLazy = Lazy.TRUE)
@ComponentScan(« fax »)
@ImportXml(locations = « applicationContext-fax2u-test.xml »)
@AnnotationDrivenTx(transactionManager = « transactionManager »)
public class ApplicationConfigTest {
@Bean
public ProxyFactoryBean faxService() {
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
try {
proxyFactoryBean.setProxyInterfaces(new Class[]{IFaxService.class});
proxyFactoryBean.setInterceptorNames(new String[]{« faxServiceInterceptor », « faxServiceBean »});
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return proxyFactoryBean;
}
@Bean
public TransactionProxyFactoryBean faxServiceBean() {
TransactionProxyFactoryBean transactionProxyFactoryBean = transactionProxy();
transactionProxyFactoryBean.setTarget(« faxServiceTarget »);
transactionProxyFactoryBean.setTransactionAttributeSource(new AnnotationTransactionAttributeSource());
return transactionProxyFactoryBean;
}
@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager();
hibernateTransactionManager.setSessionFactory(sessionFactory());
return hibernateTransactionManager;
}
@Bean()
public TransactionProxyFactoryBean transactionProxy() {
TransactionProxyFactoryBean transactionProxyFactoryBean = new TransactionProxyFactoryBean();
transactionProxyFactoryBean.setTransactionManager(transactionManager());
Properties properties = new Properties();
properties.put(« * », « PROPAGATION_REQUIRED »);
transactionProxyFactoryBean.setTransactionAttributes(properties);
return transactionProxyFactoryBean;
}
@Bean(scope = « singleton »)
public SessionFactory sessionFactory() {
AnnotationSessionFactoryBean annotationSessionFactoryBean = new AnnotationSessionFactoryBean();
annotationSessionFactoryBean.setConfigLocation(new ClassPathResource(« test.hibernate.cfg.xml »));
Properties props = new Properties();
props.put(« hibernate.c3p0.autoCommitOnClose », true);
props.put(« hibernate.autoCommitOnClose », true);
props.put(« hibernate.autocommit », true);
props.put(« hibernate.connection.release_mode », « auto »);
props.put(« hibernate.transaction.auto_close_session », true);
annotationSessionFactoryBean.setHibernateProperties(props);
try {
annotationSessionFactoryBean.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
return annotationSessionFactoryBean.getConfiguration().buildSessionFactory();
}
}
muchas gracias
Lien direct : http://s3.amazonaws.com/dist.springframework.org/milestone/SJC/spring-javaconfig-1.0.0.M4.zip
oups jai joué le gros boulet la ….on va dire que c’est la fatigue :$
merci pour la rapidité e ta réponse !! (impressionnante
Par contre y a t il un moyen simple de récupérer la version m4 de javaconfig ?
sur « http://jira.springframework.org/browse/SJC-147″ ils proposent une méthode mais j’aurai aimé savoir s’il n’en existait,pas une plus simple, genre un truc du style :
org.springframework.javaconfig
spring-javaconfig
1.0.0.m4
(je sais , la fatigue, la faignantise, je file un mauvais coton
dans tous les cas , merci beaucoup pour ton aide !!
a+
Bonne soirée
Il est déclaré en Java juste en dessous :
@Bean
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(dataSource());
}
JavaConfig va prendre les méthodes annotées avec @Bean et les transformer en un bean du nom de la méthode (txManager ici)
Salut Batiste,
merci pour ce tuto très instructrif ! néanmoins j’ai une question (sans doute de newbee) mais qui me turlupine … :
quand tu écris :
«
@Configuration(defaultLazy = Lazy.TRUE)
@ImportXML(« classpath:test/datasource-config.xml »)
@ComponentScan(« test.services »)
@AnnotationDrivenTx(transactionManager= »txManager »)
«
puis
« # @AnnotationDrivenTx(transactionManager= »txManager ») : Permet d’utiliser Spring transaction avec les annotations et de déclarer le transaction manager. «
Où définis tu ce fameux transaction manager ? dans le fichier de configuration de spring ? ou bien est ce une classe que tu as implémenté.
Merci
ps : ma question sous entend peu être que j’ai mal compris quelques chose, dans ce cas si tu peux m’éclairer cela serait sympas …
a+
Pour ce qui est de Maven, on peut trouver ça dans la documentation : http://static.springframework.org/spring-javaconfig/docs/1.0.0.M4/reference/html/ch01s07.html#jars-milestone-build-maven
Merci pour ce billet très instructif. Malheureusement je ne trouve pas de repository Maven pour cette librairie.
org.springframework.javaconfig
spring-javaconfig
1.0.0.M4
Si quelqu’un a une idée…
J’ai jamais essayé Guice, mais c’est vrai qu’il faudrait que je teste un jour ?
Par contre, je suis en train de découvrir que ce projet n’est pas exempt de bug. Par exemple, il est impossible de configurer le scan de composant avec le lazy-init
Ce qui est bloquant pour moi, je vais essayer de trouver une parade, mais pour le moment, j’ai pas de réponses sur le forum officiel.
Salut et merci pour ce billet
Au fait, je me demandais, pourquoi pas Guice qui est justement fait pour la DI par programmation ? mais du coup, tu perds les autres composants Spring, genre le gestionnaire de transactions, Spring JDBC, son abstraction du remoting, etc.