2017-09-28 5 views
2

Longue histoire courte:

Est-il possible d'interpréter la chaîne résultant de ${my.property} comme une expression Spel dans une annotation @Value sans utiliser convertisseurs, p.ex. quelque chose comme @Value("#{${my.property}})? J'ai une usine abstraite (simplifiée) qui me permet de construire des objets communs qui font partie de la configuration de mon système.

@Component 
public class Factory { 
    public Product makeVal(int x) { return new Product(5); } 
} 

Afin d'être plus flexible, je voudrais permettre aux utilisateurs d'écrire des expressions Spel dans le fichier app.properties, de sorte que l'usine peut être directement accessible:

my.property = @Factory.makeVal(12) 

Maintenant, dans la classe besoin de cette propriété, pour atteindre mon objectif, j'ai écrit le code suivant.

@Value("#{${my.property}}") 
private Product obj; 

Je pensais que ${my.property} serait macro-être élargi et évalué par #{} comme l'expression Spel correspondante, @Factory.makeVal(12) dans l'exemple ci-dessus. Malheureusement, ce n'était pas le cas, et le chargement du contexte Spring a entraîné une erreur indiquant qu'il ne pouvait pas convertir une chaîne (la valeur de la propriété ${my.property}) en le type de destination Product.

Maintenant, j'ai résolu cela en écrivant une classe implémentant Converter<String, Product>, mais il est très compliqué que j'ai besoin d'évaluer par programmation la chaîne comme une expression SpEL en instanciant le ExpressionParser et ainsi de suite.

Mais existe-t-il une solution plus simple? Existe-t-il une seule expression SpEL à mettre dans les annotations @Value qui me permet simplement d'évaluer ${my.property} comme une expression SpEL en elle-même, s'il vous plaît?

Répondre

2

Peut-être il suffit de remplacer @Factory par factory dans la valeur de la propriété. Ce test passe pour moi:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = { SpelTest.Config.class }) 
public class SpelTest 
{ 
    @Value("#{${my.property}}") 
    Product _product; 

    @Test 
    public void evaluating_spel_from_property_value() throws Exception 
    { 
     Assert.assertEquals(1234, _product.value); 
    } 

    @Component 
    public static class Factory 
    { 
     public Product makeVal(int x) { return new Product(x); } 
    } 

    public static class Product 
    { 
     public final int value; 

     public Product(final int value) { this.value = value; } 
    } 

    @Configuration 
    @ComponentScan(basePackageClasses = SpelTest.class) 
    public static class Config 
    { 
     @Bean 
     public Factory factory() { return new Factory(); } 

     @Bean 
     public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() { 
      final PropertySourcesPlaceholderConfigurer psc = new PropertySourcesPlaceholderConfigurer(); 
      final MutablePropertySources sources = new MutablePropertySources(); 
      sources.addFirst(new MockPropertySource() 
       .withProperty("my.property", 
          "factory.makeVal(1234)")); 
      psc.setPropertySources(sources); 
      return psc; 
     } 
    } 
}  
+1

Ouch, j'avais complètement tort. Mis à part le fait que j'ai oublié de mentionner que j'ai spécifié explicitement un nom de bean "Factory" plutôt que de laisser la "factory" implicite, il semble que l'erreur originale que j'ai eue provenait d'une annotation complètement différente. Trop fatigué, trop fatigué XD Je vais supprimer la question dès que possible, car en fait, il n'a aucun sens comme il est. Merci quand même: D –

+0

Il s'avère que je suis trop tard pour l'effacer, lol. Oh bien ...: D –