2015-10-20 3 views
0

Je travaille sur une application de démarrage de démarrage. Nous avons des fichiers de propriétés pour chaque environnement (dev, int, qa, prd etc). En ce qui concerne les haricots, certains doivent être créés différemment pour la production. Nous avons donc cette configuration:Spring/boot, profils, java config et ordre de création de haricot (Comportement inattendu ??)

@Configuration 
class MyBeans { 
    @Bean(name="someBean") 
    @Profile("prd") 
    MyBean someBeanProd() { 
     ... 
    } 

    @Bean(name="someBean") 
    MyBean someBeanDev() { 
     ... 
    } 
} 

MyBean est autowired comme suit:

@Component 
public class SomeService 
{ 
    @Autowired 
    private MyBean someBean; 
} 

Lors du démarrage de l'application avec:

-Dspring.profiles.active = prd

La méthode 'someBeanProd' est appelée (comme prévu) Le fichier rties est en cours de chargement (application-prd.properties). Pour tout autre profil, 'someBeanDev' est appelé (comme attendu) et le fichier de propriétés correspondant est chargé.

Cependant, si je change l'ordre des méthodes dans la configuration comme ci-dessous, la méthode 'someBeanDev' est appelée TOUJOURS (même si le profil actif est prd), mais le bon fichier de propriétés est utilisé.

@Configuration 
class MyBeans { 
    @Bean(name="someBean") 
    MyBean someBeanDev() { 
     ... 
    } 

    @Bean(name="someBean") 
    @Profile("prd") 
    MyBean someBeanProd() { 
     ... 
    } 
} 

Est-ce le comportement correct/prévu? Je m'attendais à ce que le printemps crée le bon bean indépendamment de l'ordre des méthodes dans le fichier de configuration.

Existe-t-il un moyen de définir un bean pour un profil, et tout autre profil devrait revenir au profil 'par défaut'?

La création du bean prd dans une classe de configuration Java différente ne fonctionne pas non plus.

Répondre

0

vous pouvez utiliser @Primary (sans spécifier le nom de haricots):

@Bean 
public MyBean someBeanDev() { 
    return new MyBean("dev"); 
} 

@Primary 
@Profile("prd") 
@Bean 
public MyBean someBeanProd() { 
    return new MyBean("prod"); 
} 

Dans ce cas, les deux méthodes @Bean sont appelées si le profil est « prd » mais toute @Autowired MyBean aurez seulement le MyBean est revenu par someBeanProd(). Ce cas peut être utile si vous souhaitez également avoir @Autowire Collection<MyBean>.

Ou utiliser @ConditionalOnMissingBean avec le nom de haricot (ou classe de haricot avec l'attribut value):

@Configuration 
public class ConfProd { 

    @Profile("prd") 
    @Bean(name = "someBean") 
    public MyBean someBeanProd() { 
     return new MyBean("prod"); 
    } 
} 

@Configuration 
public class ConfDev { 

    @ConditionalOnMissingBean(name = "someBean") 
    @Bean(name = "someBean") 
    public MyBean someBeanDev() { 
     return new MyBean("dev"); 
    } 
} 

Dans ce cas, une seule méthode est appelée @Bean dependending du profil spécifié.

+0

J'ai essayé l'approche avec @AutoConfigureAfter, et cela ne fonctionne toujours pas. – brnzn

+0

Désolé, appuyez sur entrer trop tôt ... Merci pour votre réponse. J'ai essayé l'approche avec @AutoConfigureAfter, et cela ne fonctionne toujours pas. Fait intéressant, si la classe prd config est alphabétiquement après la classe dev config, alors spring utilise le bon bean (avec ou sans l'annotation AutoConfigureAfter). Par exemple: DevConfig, ProdConfig = fonctionne correctement DevConfig, Config = ne fonctionne pas Je n'ai pas essayé la première approche, car je ne veux pas créer de beans s'ils ne sont pas nécessaires. – brnzn

+0

J'ai le même comportement que le vôtre, ce qui n'est pas simple IMO. Quoi qu'il en soit, j'ai édité ma réponse (deuxième approche) et celle-ci devrait fonctionner. –

0

J'ai remarqué ce comportement aussi, une solution serait de garder les différents grains de profil dans les différentes classes annotées @Profile (il était un peu un vrai problème, mais je me souviens qu'il marchait bien)

Par ex

disons que vous avez deux implémentations pour Bean1 et Bean2 dans votre profil de production et deux implémentations différentes de votre profil de mise en scène

vous voulez créer deux classes de configuration

@Configuration 
@Profile({"production"}) 
public class ConfigProduction { 
    @Bean Bean1 bean1(){ return prod impl;}] 
    @Bean Bean2 bean2(){ return prod impl;} 
} 

@Configuration 
@Profile({"staging"}) 
public class ConfigStaging { 
    @Bean Bean1 bean1(){ return staging impl;}] 
    @Bean Bean2 bean2(){ return staging impl;} 
} 

dans votre application par défaut. propriétés définir la production (ou ce que vous préférez) comme le profil actif

spring.profiles.active = production, d'avoir un comportement de type «fallback»

Faites un essai