Frühlingsprofile

1. Übersicht

In diesem Tutorial konzentrieren wir uns auf die Einführung von Profilen im Frühjahr.

Profile sind ein Kernmerkmal des Frameworks. Sie ermöglichen es uns, unsere Beans verschiedenen Profilen zuzuordnen, z. B. dev , test und prod .

Wir können dann verschiedene Profile in verschiedenen Umgebungen aktivieren, um nur die Beans zu booten, die wir benötigen.

2. Verwenden Sie @Profile für eine Bean

Beginnen wir einfach und schauen wir uns an, wie wir eine Bohne zu einem bestimmten Profil gehören lassen können. Wir verwenden die Annotation @Profile - wir ordnen die Bean diesem bestimmten Profil zu . Die Anmerkung enthält einfach die Namen eines (oder mehrerer) Profile.

Stellen Sie sich ein grundlegendes Szenario vor: Wir haben eine Bean, die nur während der Entwicklung aktiv sein sollte, aber nicht in der Produktion bereitgestellt wird.

Wir beschriften die Bohne mit einem Entwickler - Profil, und es wird nur in dem Behälter während der Entwicklung vorhanden sein. In der Produktion wird der Entwickler einfach nicht aktiv sein:

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

Als kurze Randnotiz können Profilnamen auch mit einem NOT-Operator versehen werden, z. B. ! Dev , um sie von einem Profil auszuschließen.

Im Beispiel wird die Komponente nur aktiviert, wenn das Entwicklungsprofil nicht aktiv ist:

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

3. Deklarieren Sie Profile in XML

Profile können auch in XML konfiguriert werden. DasDas Tag verfügt über ein Profilattribut , das durch Kommas getrennte Werte der entsprechenden Profile verwendet:

4. Legen Sie Profile fest

Der nächste Schritt besteht darin, die Profile so zu aktivieren und festzulegen, dass die entsprechenden Beans im Container registriert werden.

Dies kann auf verschiedene Arten geschehen, die wir in den folgenden Abschnitten untersuchen werden.

4.1. Programmatisch über die WebApplicationInitializer- Schnittstelle

In Webanwendungen kann WebApplicationInitializer verwendet werden, um den ServletContext programmgesteuert zu konfigurieren .

Es ist auch ein sehr praktischer Ort, um unsere aktiven Profile programmgesteuert festzulegen:

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

4.2. Programmatisch über ConfigurableEnvironment

Wir können Profile auch direkt in der Umgebung festlegen:

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

4.3. Kontextparameter in web.xml

Ebenso können wir die aktiven Profile in der Datei web.xml der Webanwendung mithilfe eines Kontextparameters definieren:

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

4.4. JVM-Systemparameter

Die Profilnamen können auch über einen JVM-Systemparameter übergeben werden. Diese Profile werden beim Start der Anwendung aktiviert:

-Dspring.profiles.active=dev

4.5. Umgebungsvariable

In einer Unix-Umgebung können Profile auch über die Umgebungsvariable aktiviert werden :

export spring_profiles_active=dev

4.6. Maven-Profil

Federprofile können auch über Maven-Profile aktiviert werden, indem die Konfigurationseigenschaft spring.profiles.active angegeben wird .

In jedem Maven-Profil können wir eine spring.profiles.active- Eigenschaft festlegen :

  dev  true   dev    prod  prod   

Sein Wert wird verwendet, um den Platzhalter @ [email protected] in application.properties zu ersetzen :

[email protected]@

Jetzt müssen wir die Ressourcenfilterung in pom.xml aktivieren :

   src/main/resources true   ... 

und fügen Sie einen -P- Parameter hinzu, um zu wechseln, welches Maven-Profil angewendet wird:

mvn clean package -Pprod

Dieser Befehl packt die Anwendung für das Produktprofil . Es gilt auch für den spring.profiles.active Wert prod für diese Anwendung , wenn es ausgeführt wird .

4.7. @ActiveProfile in Tests

Mithilfe von Tests können Sie ganz einfach angeben, welche Profile mithilfe der Annotation @ActiveProfile aktiv sind , um bestimmte Profile zu aktivieren:

@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

In diesem Artikel haben wir erläutert, wie Sie ein Profil auf einer Bean definieren und dann die richtigen Profile in unserer Anwendung aktivieren .

Schließlich haben wir unser Verständnis von Profilen anhand eines einfachen, aber realen Beispiels validiert.

Die Implementierung dieses Tutorials finden Sie im GitHub-Projekt.