Profils de ressort

1. Vue d'ensemble

Dans ce didacticiel, nous allons nous concentrer sur l'introduction des profils au printemps.

Les profils sont une fonctionnalité essentielle du framework - nous permettant de mapper nos beans à différents profils - par exemple, dev , test et prod .

Nous pouvons ensuite activer différents profils dans différents environnements pour amorcer uniquement les beans dont nous avons besoin.

2. Utilisez @Profile sur un Bean

Commençons simplement et voyons comment nous pouvons faire en sorte qu'un bean appartienne à un profil particulier. Nous utilisons l' annotation @Profile - nous mappons le bean à ce profil particulier ; l'annotation prend simplement les noms d'un (ou plusieurs) profils.

Considérez un scénario de base: nous avons un bean qui ne devrait être actif que pendant le développement mais pas déployé en production.

Nous annoter que le haricot avec un dev profil, et il ne sera présent dans le conteneur au cours du développement. Dans la production, le dev simplement ne sera pas actif:

@Component @Profile("dev") public class DevDatasourceConfig

En bref, les noms de profil peuvent également être précédés d'un opérateur NOT, par exemple ! Dev , pour les exclure d'un profil.

Dans l'exemple, le composant est activé que si dev profil est pas actif:

@Component @Profile("!dev") public class DevDatasourceConfig

3. Déclarer des profils en XML

Les profils peuvent également être configurés en XML. leLa balise a un attribut profiles , qui prend les valeurs séparées par des virgules des profils applicables:

4. Définir les profils

L'étape suivante consiste à activer et à définir les profils afin que les beans respectifs soient enregistrés dans le conteneur.

Cela peut être fait de différentes manières, que nous explorerons dans les sections suivantes.

4.1. Programmation via l' interface WebApplicationInitializer

Dans les applications Web, WebApplicationInitializer peut être utilisé pour configurer le ServletContext par programmation.

C'est également un emplacement très pratique pour définir nos profils actifs par programmation:

@Configuration public class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { servletContext.setInitParameter( "spring.profiles.active", "dev"); } }

4.2. Programmation via un environnement configurable

Nous pouvons également définir des profils directement sur l'environnement:

@Autowired private ConfigurableEnvironment env; ... env.setActiveProfiles("someProfile");

4.3. Paramètre de contexte dans web.xml

De même, nous pouvons définir les profils actifs dans le fichier web.xml de l'application Web, à l'aide d'un paramètre de contexte:

 contextConfigLocation /WEB-INF/app-config.xml   spring.profiles.active dev 

4.4. Paramètre système JVM

Les noms de profil peuvent également être transmis via un paramètre système JVM. Ces profils seront activés au démarrage de l'application:

-Dspring.profiles.active=dev

4.5. Variable d'environnement

Dans un environnement Unix, les profils peuvent également être activés via la variable d'environnement :

export spring_profiles_active=dev

4.6. Profil Maven

Les profils de ressort peuvent également être activés via les profils Maven, en spécifiant la propriété de configuration spring.profiles.active .

Dans chaque profil Maven, nous pouvons définir une propriété spring.profiles.active :

  dev  true   dev    prod  prod   

Sa valeur sera utilisée pour remplacer l' espace réservé @ [email protected] dans application.properties :

[email protected]@

Nous devons maintenant activer le filtrage des ressources dans pom.xml :

   src/main/resources true   ... 

et ajoutez un paramètre -P pour changer le profil Maven qui sera appliqué:

mvn clean package -Pprod

Cette commande conditionnera l'application pour le profil de production . Il applique également la valeur prod spring.profiles.active pour cette application lorsqu'elle est en cours d'exécution.

4.7. @ActiveProfile dans les tests

Les tests permettent de spécifier très facilement les profils actifs à l'aide de l' annotation @ActiveProfile pour activer des profils spécifiques:

@ActiveProfiles("dev")

So far, we've looked at multiple ways of activating profiles. Let's now see which one has priority over the other and what happens if we use more than one, from highest to lowest priority:

  1. Context parameter in web.xml
  2. WebApplicationInitializer
  3. JVM System parameter
  4. Environment variable
  5. Maven profile

5. The Default Profile

Any bean that does not specify a profile belongs to the default profile.

Spring also provides a way to set the default profile when no other profile is active — by using the spring.profiles.default property.

6. Get Active Profiles

Spring's active profiles drive the behavior of the @Profile annotation for enabling/disabling beans. However, we may also wish to access the list of active profiles programmatically.

We have two ways to do it, using Environment or spring.active.profile.

6.1. Using Environment

We can access the active profiles from the Environment object by injecting it:

public class ProfileManager { @Autowired    private Environment environment;     public void getActiveProfiles() {         for (String profileName : environment.getActiveProfiles()) {             System.out.println("Currently active profile - " + profileName);         }       } }

6.2. Using spring.active.profile

Alternatively, we could access the profiles by injecting the property spring.profiles.active:

@Value("${spring.profiles.active}") private String activeProfile;

Here, our activeProfile variable will contain the name of the profile that is currently active, and if there are several, it'll contain their names separated by a comma.

However, we should consider what would happen if there is no active profile at all. With our code above, the absence of an active profile would prevent the application context from being created. This would result in an IllegalArgumentException owing to the missing placeholder for injecting into the variable.

In order to avoid this, we can define a default value:

@Value("${spring.profiles.active:}") private String activeProfile;

Now, if no profiles are active, our activeProfile will just contain an empty string.

And if we want to access the list of them just like in the previous example, we can do it by splitting the activeProfile variable:

public class ProfileManager { @Value("${spring.profiles.active:}") private String activeProfiles; public String getActiveProfiles() { for (String profileName : activeProfiles.split(",")) { System.out.println("Currently active profile - " + profileName); } } }

7. Example: Separate Data Source Configurations Using Profiles

Now that the basics are out of the way, let's take a look at a real example.

Consider a scenario where we have to maintain the data source configuration for both the development and production environments.

Let's create a common interface DatasourceConfig that needs to be implemented by both data source implementations:

public interface DatasourceConfig { public void setup(); }

Following is the configuration for the development environment:

@Component @Profile("dev") public class DevDatasourceConfig implements DatasourceConfig { @Override public void setup() { System.out.println("Setting up datasource for DEV environment. "); } }

And configuration for the production environment:

@Component @Profile("production") public class ProductionDatasourceConfig implements DatasourceConfig { @Override public void setup() { System.out.println("Setting up datasource for PRODUCTION environment. "); } }

Now let's create a test and inject our DatasourceConfig interface; depending on the active profile, Spring will inject DevDatasourceConfig or ProductionDatasourceConfig bean:

public class SpringProfilesWithMavenPropertiesIntegrationTest { @Autowired DatasourceConfig datasourceConfig; public void setupDatasource() { datasourceConfig.setup(); } }

When the dev profile is active, Spring injects DevDatasourceConfig object, and when calling then setup() method, the following is the output:

Setting up datasource for DEV environment.

8. Profiles in Spring Boot

Spring Boot supports all the profile configuration outlined so far, with a few additional features.

The initialization parameter spring.profiles.active, introduced in Section 4, can also be set up as a property in Spring Boot to define currently active profiles. This is a standard property that Spring Boot will pick up automatically:

spring.profiles.active=dev

To set profiles programmatically, we can also use the SpringApplication class:

SpringApplication.setAdditionalProfiles("dev");

To set profiles using Maven in Spring Boot, we can specify profile names under spring-boot-maven-plugin in pom.xml:

  org.springframework.boot spring-boot-maven-plugin   dev    ... 

and execute the Spring Boot-specific Maven goal:

mvn spring-boot:run

But the most important profiles-related feature that Spring Boot brings is profile-specific properties files. These have to be named in the format application-{profile}.properties.

Spring Boot will automatically load the properties in an application.properties file for all profiles, and the ones in profile-specific .properties files only for the specified profile.

For example, we can configure different data sources for dev and production profiles by using two files named application-dev.properties and application-production.properties:

In the application-production.properties file, we can set up a MySql data source:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/db spring.datasource.username=root spring.datasource.password=root

Then we can configure the same properties for the dev profile in the application-dev.properties file, to use an in-memory H2 database:

spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 spring.datasource.username=sa spring.datasource.password=sa

In this way, we can easily provide different configurations for different environments.

9. Conclusion

Dans cet article, nous avons expliqué comment définir un profil sur un bean et comment activer ensuite les bons profils dans notre application.

Enfin, nous avons validé notre compréhension des profils avec un exemple simple mais réel.

L'implémentation de ce tutoriel se trouve dans le projet GitHub.