Profili a molla

1. Panoramica

In questo tutorial, ci concentreremo sull'introduzione dei profili in primavera.

I profili sono una caratteristica fondamentale del framework, permettendoci di mappare i nostri bean su diversi profili , ad esempio dev , test e prod .

Possiamo quindi attivare diversi profili in diversi ambienti per avviare solo i bean di cui abbiamo bisogno.

2. Utilizzare @Profile su un bean

Iniziamo in modo semplice e vediamo come possiamo far appartenere un fagiolo a un profilo particolare. Usiamo l' annotazione @Profile - stiamo mappando il bean a quel particolare profilo ; l'annotazione prende semplicemente i nomi di uno (o più) profili.

Considera uno scenario di base: abbiamo un bean che dovrebbe essere attivo solo durante lo sviluppo ma non distribuito in produzione.

Annotiamo quel bean con un profilo dev e sarà presente nel container solo durante lo sviluppo. In produzione, il dev semplicemente non sarà attivo:

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

Come breve nota a margine, i nomi dei profili possono anche essere preceduti da un operatore NOT, ad esempio ! Dev , per escluderli da un profilo.

Nell'esempio, il componente viene attivato solo se il profilo dev non è attivo:

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

3. Dichiarare i profili in XML

I profili possono anche essere configurati in XML. Iltag ha un attributo di profili , che accetta valori separati da virgole dei profili applicabili:

4. Impostare i profili

Il passaggio successivo consiste nell'attivare e impostare i profili in modo che i rispettivi bean siano registrati nel contenitore.

Questo può essere fatto in una varietà di modi, che esploreremo nelle sezioni seguenti.

4.1. A livello di codice tramite l' interfaccia WebApplicationInitializer

Nelle applicazioni Web, WebApplicationInitializer può essere utilizzato per configurare ServletContext a livello di codice .

È anche una posizione molto comoda per impostare i nostri profili attivi a livello di programmazione:

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

4.2. A livello di codice tramite ConfigurableEnvironment

Possiamo anche impostare i profili direttamente sull'ambiente:

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

4.3. Parametro di contesto in web.xml

Allo stesso modo, possiamo definire i profili attivi nel file web.xml dell'applicazione web, utilizzando un parametro di contesto:

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

4.4. Parametro di sistema JVM

I nomi dei profili possono anche essere passati tramite un parametro di sistema JVM. Questi profili verranno attivati ​​durante l'avvio dell'applicazione:

-Dspring.profiles.active=dev

4.5. Variabile d'ambiente

In un ambiente Unix, i profili possono essere attivati ​​anche tramite la variabile d'ambiente :

export spring_profiles_active=dev

4.6. Profilo Maven

I profili delle molle possono essere attivati ​​anche tramite i profili Maven, specificando la proprietà di configurazione spring.profiles.active .

In ogni profilo Maven, possiamo impostare una proprietà spring.profiles.active :

  dev  true   dev    prod  prod   

Il suo valore verrà utilizzato per sostituire il segnaposto @ [email protected] in application.properties :

[email protected]@

Ora dobbiamo abilitare il filtro delle risorse in pom.xml :

   src/main/resources true   ... 

e aggiungi un parametro -P per cambiare il profilo Maven che verrà applicato:

mvn clean package -Pprod

Questo comando comprimerà l'applicazione per il profilo prod . Si applica anche il spring.profiles.active valore di prod per questa applicazione quando è in esecuzione.

4.7. @ActiveProfile nei test

I test rendono molto facile specificare quali profili sono attivi utilizzando l' annotazione @ActiveProfile per abilitare profili specifici:

@ActiveProfiles("dev")

Finora, abbiamo esaminato diversi modi per attivare i profili. Vediamo ora quale ha la priorità sull'altro e cosa succede se ne usiamo più di uno, dalla priorità più alta a quella più bassa:

  1. Parametro di contesto in web.xml
  2. WebApplicationInitializer
  3. Parametro di sistema JVM
  4. Variabile d'ambiente
  5. Profilo di Maven

5. Il profilo predefinito

Qualsiasi bean che non specifica un profilo appartiene al profilo predefinito .

Spring fornisce anche un modo per impostare il profilo predefinito quando nessun altro profilo è attivo, utilizzando la proprietà spring.profiles.default .

6. Ottieni profili attivi

I profili attivi di Spring guidano il comportamento dell'annotazione @Profile per abilitare / disabilitare i bean. Tuttavia, potremmo anche voler accedere all'elenco dei profili attivi a livello di programmazione.

Abbiamo due modi per farlo, utilizzando Environment o spring.active.profile .

6.1. Utilizzo dell'ambiente

Possiamo accedere ai profili attivi dall'oggetto Ambiente iniettandolo:

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

6.2. Utilizzando spring.active.profile

In alternativa, potremmo accedere ai profili iniettando la proprietà spring.profiles.active :

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

Qui, la nostra variabile activeProfile conterrà il nome del profilo attualmente attivo e, se ce ne sono diversi, conterrà i loro nomi separati da una virgola.

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 questo articolo, abbiamo discusso come definire un profilo su un bean e come abilitare quindi i profili corretti nella nostra applicazione.

Infine, abbiamo convalidato la nostra comprensione dei profili con un esempio semplice ma reale.

L'implementazione di questo tutorial può essere trovata nel progetto GitHub.