63 votes

Comment réaliser une importation de ressources conditionnelle dans un contexte XML Spring?

Ce que je voudrais, c'est la capacité à "dynamique" (c'est à dire basée sur une propriété définie dans un fichier de configuration) activer/désactiver l'importation d'un enfant Printemps contexte XML.

J'imagine quelque chose comme:

<import condition="some.property.name" resource="some-context.xml"/>

Lorsque le bien est résolu (booléenne) et lorsque la valeur est true, le contexte est importé, sinon il ne l'est pas.

Certains de mes recherches jusqu'à présent:

  • L'écriture d'un personnalisé NamespaceHandler (et d'autres classes), de sorte que je peux enregistrer mon propre élément dans mon propre espace de noms. Par exemple: <myns:import condition="some.property.name" resource="some-context.xml"/>

    Le problème avec cette approche est que je ne veux pas reproduire la totalité de la ressource de l'importation de la logique à partir du Printemps et il n'est pas évident pour moi ce que j'ai besoin de déléguer pour ce faire.

  • Primordial DefaultBeanDefinitionDocumentReader à étendre le comportement de "l'importation" de l'élément de l'analyse et de l'interprétation (ce qui arrive-t-il dans l' importBeanDefinitionResource méthode). Cependant, je ne suis pas sûr de l'endroit où je peux enregistrer cette extension.

44voto

Stephen C Points 255558

Le plus proche que vous pouvez obtenir en utilisant la norme de Printemps composants est:

<import resource="Whatever-${yyzzy}.xml"/>

${xyzzy} interpole une propriété à partir des propriétés du système. (J'utilise un hacky version personnalisée du contexte de la classe loader qui ajoute des propriétés à partir d'autres endroits pour le système de propriétés de l'objet avant de commencer le processus de chargement.)

Mais vous pouvez aussi sortir avec l'importation des tas de trucs inutiles ... et différentes astuces pour seule cause la nécessaire haricots être instanciés. Ces astuces comprennent:

  • espace réservé et des biens de substitution
  • la sélection de différentes fèves à l'aide de la nouvelle Printemps expression de la langue,
  • bean alias avec des espaces dans le nom de la cible,
  • paresseux haricot d'initialisation, et
  • smart bean usines.

28voto

ptomli Points 5778

C'est maintenant tout à fait possible, à l'aide de Printemps 4.

Dans votre contenu principal de l'application fichier

<bean class="com.example.MyConditionalConfiguration"/>

Et le MyConditionalConfiguration ressemble

@Configuration
@Conditional(MyConditionalConfiguration.Condition)
@ImportResource("/com/example/context-fragment.xml")
public class MyConditionalConfiguration {
    static class Condition implements ConfigurationCondition {
         @Override
         public ConfigurationPhase getConfigurationPhase() {
             return ConfigurationPhase.PARSE_CONFIGURATION;
         }
         @Override
         public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
             // only load context-fragment.xml if the system property is defined
             return System.getProperty("com.example.context-fragment") != null;
         }
    }
}

Et puis enfin, vous mettez les haricots définitions que vous souhaitez inclure dans l' /com/example/context-fragment.xml

Voir la JavaDoc pour @Conditionnel

27voto

lolotron Points 577

Comme mentionné précédemment, ceci peut être facilement réalisé avec des profils si vous utilisez Spring 3.1+

 <!-- default configuration - will be loaded if no profile is specified -->
<!-- This will only work if it's put at the end of the configuration file -->
<!-- so no bean definitions after that -->
<beans profile="default">
    <import resource="classpath:default.xml" />
</beans>
<!-- some other profile -->
<beans profile="otherProfile">
    <import resource="classpath:other-profile.xml" />
</beans>
 

otherProfile peut être facilement activé avec par exemple

 mvn install -Dspring.profiles.active=otherProfile
 

Si vous utilisez des profils différents dans les tests, ajoutez simplement -DforkMode=never pour vous assurer que les tests s'exécutent dans la même machine virtuelle. Par conséquent, le paramètre spring.profiles.active ne sera pas perdu.

23voto

teabot Points 7711

Avec Spring 3.1.x, vous pouvez utiliser des profils de bean pour réaliser une importation conditionnelle de ressources et une instanciation de bean. Ceci est bien sûr sans aide si vous utilisez une version antérieure :)

20voto

espinchi Points 1373

Pour l'enregistrement, Robert Maldon explique comment réaliser conditionnelle définition de haricots dans ce post: http://robertmaldon.blogspot.com/2007/04/conditionally-defining-spring-beans.html. Il est un peu long à copier ici (d'ailleurs je ne pense pas que je doit copier-coller de son article, de toute façon).

Le résultat final avec cette approche, adaptée à votre exemple, est:

<condbean:cond test="${some.property.name}">
  <import resource="some-context.xml"/>
</condbean:cond>

Il n'est certainement pas si simple que Stephen C est la solution, mais il est beaucoup plus puissant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X