1. Información general
En este tutorial, nos centraremos en la introducción de Perfiles en Spring.
Los perfiles son una característica central del marco, lo que nos permite asignar nuestros beans a diferentes perfiles , por ejemplo, dev , test y prod .
Luego, podemos activar diferentes perfiles en diferentes entornos para arrancar solo los beans que necesitamos.
2. Use @Profile en un Bean
Comencemos de manera simple y veamos cómo podemos hacer que un bean pertenezca a un perfil en particular. Usamos la anotación @Profile - estamos mapeando el bean a ese perfil en particular ; la anotación simplemente toma los nombres de uno (o múltiples) perfiles.
Considere un escenario básico: tenemos un bean que solo debería estar activo durante el desarrollo pero no desplegado en producción.
Nos anotamos que el frijol con un dev perfil, y sólo estará presente en el contenedor durante el desarrollo. En la producción, el dev simplemente no estará activo:
@Component @Profile("dev") public class DevDatasourceConfig
Como nota al margen rápida, los nombres de los perfiles también pueden tener un prefijo NOT, por ejemplo ,! Dev , para excluirlos de un perfil.
En el ejemplo, el componente se activa sólo si dev perfil no está activa:
@Component @Profile("!dev") public class DevDatasourceConfig
3. Declarar perfiles en XML
Los perfiles también se pueden configurar en XML. lostiene un atributo de perfiles , que toma valores separados por comas de los perfiles aplicables:
4. Establecer perfiles
El siguiente paso es activar y configurar los perfiles para que los respectivos beans queden registrados en el contenedor.
Esto se puede hacer de varias formas, que exploraremos en las siguientes secciones.
4.1. Programáticamente a través de la interfaz WebApplicationInitializer
En aplicaciones web, WebApplicationInitializer se puede utilizar para configurar ServletContext mediante programación.
También es una ubicación muy útil para configurar nuestros perfiles activos mediante programación:
@Configuration public class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { servletContext.setInitParameter( "spring.profiles.active", "dev"); } }
4.2. Programáticamente a través de ConfigurableEnvironment
También podemos configurar perfiles directamente en el entorno:
@Autowired private ConfigurableEnvironment env; ... env.setActiveProfiles("someProfile");
4.3. Parámetro de contexto en web.xml
Del mismo modo, podemos definir los perfiles activos en el archivo web.xml de la aplicación web, utilizando un parámetro de contexto:
contextConfigLocation /WEB-INF/app-config.xml spring.profiles.active dev
4.4. Parámetro del sistema JVM
Los nombres de los perfiles también se pueden pasar a través de un parámetro del sistema JVM. Estos perfiles se activarán durante el inicio de la aplicación:
-Dspring.profiles.active=dev
4.5. Variable ambiental
En un entorno Unix, los perfiles también se pueden activar mediante la variable de entorno :
export spring_profiles_active=dev
4.6. Perfil de Maven
Los perfiles Spring también se pueden activar a través de perfiles Maven, especificando la propiedad de configuración spring.profiles.active .
En cada perfil de Maven, podemos establecer una propiedad spring.profiles.active :
dev true dev prod prod
Su valor se utilizará para reemplazar el marcador de posición @ [email protected] en application.properties :
[email protected]@
Ahora necesitamos habilitar el filtrado de recursos en pom.xml :
src/main/resources true ...
y agregue un parámetro -P para cambiar qué perfil de Maven se aplicará:
mvn clean package -Pprod
Este comando empaquetará la aplicación para el perfil prod . También aplica el valor spring.profiles.active prod para esta aplicación cuando se está ejecutando.
4.7. @ActiveProfile en pruebas
Las pruebas hacen que sea muy fácil especificar qué perfiles están activos usando la anotación @ActiveProfile para habilitar perfiles específicos:
@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:
- Context parameter in web.xml
- WebApplicationInitializer
- JVM System parameter
- Environment variable
- 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
En este artículo, discutimos cómo definir un perfil en un bean y cómo habilitar los perfiles correctos en nuestra aplicación.
Finalmente, validamos nuestra comprensión de los perfiles con un ejemplo simple pero del mundo real.
La implementación de este tutorial se puede encontrar en el proyecto GitHub.