web-dev-qa-db-fra.com

Profils de printemps au niveau de la méthode?

Je voudrais présenter quelques méthodes qui ne sont exécutées que pendant le développement.

J'ai pensé que je pourrais utiliser Spring @Profile annotation ici? Mais comment puis-je appliquer cette annotation au niveau de la classe, afin que cette méthode ne soit invoquée que si le profil spécifique est configuré dans les propriétés?

spring.profiles.active=dev

Prenez ce qui suit comme pseudocode. Comment cela peut-il être fait?

class MyService {

    void run() { 
       log();
    }

    @Profile("dev")
    void log() {
       //only during dev
    }
}
20
membersound

COMME vous pouvez le lire http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/Profile.html

L'annotation @Profile peut être utilisée de l'une des manières suivantes:

en tant qu'annotation de niveau type sur toute classe annotée directement ou indirectement avec @Component, y compris les classes @Configuration en tant que méta-annotation, dans le but de composer des annotations de stéréotypes personnalisés Si une classe @Configuration est marqué avec @Profile, toutes les méthodes @Bean et les annotations @Import associées à cette classe seront ignorées à moins qu'un ou plusieurs des profils spécifiés ne soient actifs. Ceci est très similaire au comportement de Spring XML: si l'attribut profile de l'élément beans est fourni par exemple, l'élément beans ne sera pas analysé à moins que les profils 'p1' et/ou 'p2' n'aient été activés. De même, si une classe @Component ou @Configuration est marquée avec @Profile ({"p1", "p2"}), cette classe ne sera pas enregistrée/traitée à moins que les profils 'p1' et/ou 'p2' n'aient été activés.

Ainsi, une annotation @Profile sur une classe, s'applique à toutes ses méthodes et à ses importations. Pas à la classe.

Ce que vous essayez de faire pourrait probablement être réalisé en ayant deux classes qui implémentent la même interface et en injectant l'une ou l'autre en fonction du profil. Jetez un œil à la réponse à cette question.

injection de dépendances basée sur des annotations qui gère différents environnements

11
Andres

Pour les futurs lecteurs qui ne veulent pas avoir plusieurs @Beans annoté avec @Profile, cela pourrait aussi être une solution:

class MyService {

   @Autowired
   Environment env;

   void run() { 
      if (Arrays.asList(env.getActiveProfiles()).contains("dev")) {
         log();
      }
   }

   void log() {
      //only during dev
   }
}
13
Niels Masdorp

Je voulais juste ajouter que réponse disant que c'est possible avec le ressort actuel au niveau de la méthode est manifestement faux. L'utilisation de @Profile sur les méthodes en général ne fonctionnera pas - les seules méthodes sur lesquelles elle fonctionnera sont dans la classe @Configuration avec l'annotation @Bean dessus.

Je lance un test rapide avec Spring 4.2.4, où on a vu que

  • @Profile dans les méthodes de création de bean de classe @Configuration fonctionnent
  • @Profile dans les méthodes d'un bean ne fonctionne pas (et ne devrait pas fonctionner - les documents sont un peu ambigus)
  • Le niveau de classe @Profile fonctionne si et seulement si il est dans le même contexte que la définition du bean, dans la classe de configuration ou si l'analyse contextuelle est utilisée, il
  • env.acceptsProfiles ("profile"), Arrays.asList (env.getActiveProfiles ()). contains ("profile") works

Classe de test:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import Java.util.Arrays;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ProfileTest.ProfileTestConfiguration.class })
@ActiveProfiles("test")
public class ProfileTest {
    static class SomeClass {}
    static class OtherClass {}
    static class ThirdClass {
        @Profile("test")
        public void method() {}
    }
    static class FourthClass {
        @Profile("!test")
        public void method() {}
    }

    static class ProfileTestConfiguration {
        @Bean
        @Profile("test")
        SomeClass someClass() {
            return new SomeClass();
        }
        @Bean
        @Profile("!test")
        OtherClass otherClass() {
            return new OtherClass();
        }
        @Bean
        ThirdClass thirdClass() {
            return new ThirdClass();
        }
        @Bean
        FourthClass fourthClass() {
            return new FourthClass();
        }
    }

    @Autowired
    ApplicationContext context;

    @Test
    public void testProfileAnnotationIncludeClass() {
        context.getBean(SomeClass.class);
    }
    @Test(expected = NoSuchBeanDefinitionException.class)
    public void testProfileAnnotationExcludeClass() {
        context.getBean(OtherClass.class);
    }
    @Test
    public void testProfileAnnotationIncludeMethod() {
        context.getBean(ThirdClass.class).method();
    }
    @Test(expected = Exception.class)  // fails
    public void testProfileAnnotationExcludeMethod() {
        context.getBean(FourthClass.class).method();
    }
}
10
eis

@Profile peut être utilisé avec la méthode et avec Java Based Configuration

par exemple. horodatage DB distinct pour PostgreSQL (LocalDateTime) et pour HSQLDB (avant 2.4.0 Timestamp):

@Autowired
private Function<LocalDateTime, T> dateTimeExtractor;

@Bean
@Profile("hsqldb")
public Function<LocalDateTime, Timestamp> getTimestamp() {
    return Timestamp::valueOf;
}

@Bean
@Profile("postgres")
public Function<LocalDateTime, LocalDateTime> getLocalDateTime() {
    return dt -> dt;
}

Jetez également un œil à exemple Spring Profiles : 3. Plus… (exemple Spring @Profile au niveau de la méthode)

7
GKislin

Possible en 4.1

L'annotation @Profile peut être utilisée de l'une des manières suivantes:

en tant qu'annotation de niveau type sur n'importe quelle classe annotée directement ou indirectement avec @Component, y compris les classes @Configuration. En tant que méta-annotation, dans le but de composer des annotations de stéréotypes personnalisées. En tant qu'annotation au niveau de la méthode sur n'importe quelle méthode @Bean

http://docs.spring.io/spring/docs/4.1.x/javadoc-api/org/springframework/context/annotation/Profile.html

7
Jorge Sanchez