Kleines Beispiel zur Verwendung von @Profile in einer Spring App mit Java Config

Thomas Darimont

Erfahrenes Mitglied
Hallo,

hier mal ein kleines Beispiel, wie man in einer Spring basierten Anwendung mit der @Profile Annotation (seit Spring 3.1) und Java Config unterschiedliche "Betriebsmodi" realisieren kann.

In unserem Beispiel haben wir eine MailService den für den es im System zwei Implementierungen gibt:
- NoopMailService //sendet keine Mails
- JavaMailService // sendet Mails via JavaMail

Je nachdem in welchem Betriebsmodi (Mail-Feature an / aus) wir die Anwendung haben wollen, soll eine andere Service-Implementierung von Spring bereitgestellt werden.

Dazu verwenden wir in unten stehendem Beispiel die @Profile Annotation von Spring.
Mit @Profile("mail-enabled") teilen wir dem Spring Container mit, die entsprechende Service Implementierung nur dann zu verwenden, wenn das Profil auch für den Spring Container aktiviert ist.

Dies kann beispielsweise über einen Aufruf der Methode:
context.getEnvironment().setActiveProfiles("mail-enabled");

oder über das setzen eines JVM Property erreicht werden:
-Dspring.profiles.active=mail-enabled

Schaut mal hier:
Java:
package de.tutorials.training;


import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;


@Configuration
@Import({NoopMailConfig.class, JavaMailConfig.class})
class AppConfig{}


@Configuration
class NoopMailConfig {
  @Bean
  public MailService service() {
    return new NoopMailService();
  }
}


@Configuration
@Profile("mail-enabled")
class JavaMailConfig {
  @Bean
  public MailService service() {
    return new JavaMailService();
  }
}


interface MailService {
  void sendMessage();
}


class NoopMailService implements MailService {
  @Override
  public void sendMessage() {
    System.out.println(getClass() + ".sendMessage() -> noop");
  }
}


class JavaMailService extends NoopMailService {
  @Override
  public void sendMessage() {
    System.out.println(getClass() + ".sendMessage() -> via javamail");
  }
}




public class SpringProfilesExample {


  public static void main(String[] args) {
    //Bootstrap spring context with "default" profile
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    context.getBean(MailService.class).sendMessage();
    context.close();


    //Bootstrap spring context with mail-enabled profile
    context = new AnnotationConfigApplicationContext();
    context.register(AppConfig.class);
    context.getEnvironment().setActiveProfiles("mail-enabled");
    context.refresh();
    context.getBean(MailService.class).sendMessage();
  }
}

Ausgabe:
Code:
Apr 17, 2013 6:01:21 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@427dac02: startup date [Wed Apr 17 18:01:21 CEST 2013]; root of context hierarchy
Apr 17, 2013 6:01:22 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2fddef87: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,appConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,de.tutorials.training.DefaultConfig#0,service]; root of factory hierarchy
class de.tutorials.training.NoopMailService.sendMessage() -> noop
Apr 17, 2013 6:01:22 PM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@427dac02: startup date [Wed Apr 17 18:01:21 CEST 2013]; root of context hierarchy
Apr 17, 2013 6:01:22 PM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2fddef87: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,appConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,de.tutorials.training.DefaultConfig#0,service]; root of factory hierarchy
Apr 17, 2013 6:01:22 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@650c892c: startup date [Wed Apr 17 18:01:22 CEST 2013]; root of context hierarchy
Apr 17, 2013 6:01:22 PM org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
INFO: Overriding bean definition for bean 'service': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=de.tutorials.training.DefaultConfig#0; factoryMethodName=service; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [de/tutorials/training/DefaultConfig.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=de.tutorials.training.Profile1Config#0; factoryMethodName=service; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [de/tutorials/training/Profile1Config.class]]
Apr 17, 2013 6:01:22 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6ff3cb0e: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,appConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,de.tutorials.training.DefaultConfig#0,service,de.tutorials.training.Profile1Config#0]; root of factory hierarchy
class de.tutorials.training.JavaMailService.sendMessage() -> via javamail

Gruß Tom