Escenarios de uso de @Perfil

prefacio

En el entorno de desarrollo empresarial real, el entorno a menudo se divide en: entorno de desarrollo, entorno de prueba y entorno de producción, y cada entorno está básicamente aislado entre sí, es decir, el entorno de desarrollo, el entorno de prueba y el entorno de producción son mutuamente excluyentes. Irrelevante. En el proceso de desarrollo anterior, si el desarrollador completaba los módulos funcionales correspondientes y pasaba la prueba unitaria, modificaba manualmente el archivo de configuración para modificar la configuración del proyecto en un entorno de prueba y lo liberaba al entorno de prueba para la prueba. Una vez superada la prueba, modifique la configuración en el entorno de producción y libérela en el entorno de producción. Esta forma de modificar manualmente la configuración, por un lado, aumenta la carga de trabajo de desarrollo y operación y mantenimiento, y la modificación manual de varios archivos de configuración siempre es propensa a problemas. Entonces, ¿hay alguna forma de resolver estos problemas? ¡La respuesta es sí! Se puede hacer completamente a través de la anotación @Profile.

1. Introducción a la anotación @Profile

Si hay varios componentes del mismo tipo en el contenedor, también puede usar la anotación @Profile para identificar qué bean obtener, lo que es especialmente útil cuando diferentes entornos usan diferentes variables. Por ejemplo, el entorno de desarrollo, el entorno de prueba y el entorno de producción usan diferentes fuentes de datos. Puede usar esta anotación para cambiar la base de datos para que se conecte sin cambiar el código.

Proceder de la siguiente:

  1. Agregue la anotación @Profile al bean, y su valor de atributo de valor es el identificador de entorno, que se puede personalizar
  2. Crear un contenedor usando un constructor sin argumentos
  3. Establezca el entorno del contenedor, cuyo valor es el ID del entorno establecido en el paso 1
  4. Establecer la clase de configuración del contenedor.
  5. actualizar contenedor

Nota: Los pasos 2, 4 y 5 son en realidad los pasos del método de construcción con parámetros, que es equivalente a desensamblar el método de construcción con parámetros e insertar una declaración para configurar el entorno del contenedor. Podemos verlos en el código fuente de Spring. , como el siguiente código.

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    
    
   this();
   register(annotatedClasses);
   refresh();
}

A continuación, veamos el código fuente de la anotación @Profile, como se muestra a continuación.

package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Profiles;
@Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
    
    
 String[] value();
}

Nota: @Profile se puede marcar no solo en los métodos, sino también en las clases de configuración.
Si se marca en la clase de configuración, todas las configuraciones en toda la clase de configuración surtirán efecto solo en el entorno especificado.
Si un bean no está marcado con la anotación @Profile, el bean se registrará en el contenedor IOC en cualquier entorno.

2. Uso de la anotación @Profile

1. Construcción del entorno

A continuación, construyamos un entorno que utilice la anotación @Profile para realizar la configuración y el cambio de entornos de desarrollo, prueba y producción. Aquí, tomamos diferentes fuentes de datos como ejemplos. Primero, agregamos las dependencias del controlador c3p0 y MySQL en el archivo pom.xml, como se muestra a continuación.

<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.44</version>
</dependency>

Después de agregar las dependencias del proyecto, creamos una nueva clase de configuración ProfileConfig en el proyecto y simulamos las fuentes de datos de los entornos de desarrollo, prueba y producción en la clase de configuración ProfileConfig, como se muestra a continuación.

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * @author 
 * @version 1.0.0
 * @description 测试多数据源
 */
@Configuration
public class ProfileConfig {
    
    
    @Bean("devDataSource")
    public DataSource dataSourceDev() throws Exception{
    
    
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_dev");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        return dataSource;
    }
    @Bean("testDataSource")
    public DataSource dataSourceTest() throws Exception{
    
    
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_test");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        return dataSource;
    }
    @Bean("prodDataDource")
    public DataSource dataSourceProd() throws Exception{
    
    
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_prod");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        return dataSource;
    }
}

Esta clase es relativamente simple, donde la anotación @Bean("devDataSource") se usa para anotar la fuente de datos utilizada en el entorno de desarrollo; la anotación @Bean("testDataSource") se usa para anotar la fuente de datos utilizada en el entorno de prueba ; usar la anotación @Bean ("prodDataDource") marca la fuente de datos utilizada en el entorno de producción.

A continuación, creamos la clase ProfileTest y creamos un nuevo método testProfile01() en la clase ProfileTest para realizar pruebas, como se muestra a continuación.

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.sql.DataSource;
import java.util.stream.Stream;

/**
 * @author 
 * @version 1.0.0
 * @description 测试类
 */
public class ProfileTest {
    
    
    @Test
    public void testProfile01(){
    
    
        // 创建IOC容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProfileConfig.class);
        String[] names = context.getBeanNamesForType(DataSource.class);
        Stream.of(names).forEach(System.out::println);
    }
}

Ejecute el método testProfile01() de la clase ProfileTest y la información de salida es la siguiente.

devDataSource
testDataSource
prodDataDource

Se puede ver que tres fuentes de datos diferentes se han registrado con éxito en el contenedor IOC, lo que indica que nuestro entorno se ha construido con éxito.

2. Registra frijoles según el entorno.

Después de que construimos con éxito el entorno, el siguiente paso es registrar los beans correspondientes en el contenedor IOC de acuerdo con diferentes entornos. Es decir, debemos registrar la fuente de datos utilizada en el entorno de desarrollo en el entorno de desarrollo; registrar la fuente de datos utilizada en el entorno de prueba en el entorno de prueba; registrar la fuente de datos utilizada en el entorno de producción en el entorno de producción. En este punto, la anotación @Profile muestra sus poderosas características.

Agregamos anotaciones @Profile a cada fuente de datos en la clase ProfileConfig, como se muestra a continuación.

@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceDev() throws Exception{
    
    
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_dev");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    return dataSource;
}
@Profile("test")
@Bean("testDataSource")
public DataSource dataSourceTest() throws Exception{
    
    
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_test");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    return dataSource;
}
@Profile("prod")
@Bean("prodDataDource")
public DataSource dataSourceProd() throws Exception{
    
    
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_prod");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    return dataSource;
}

Usamos la anotación @Profile("dev") para identificar el devDataSource registrado en el entorno de desarrollo; use la anotación @Profile("test") para identificar el testDataSource registrado en el entorno de prueba; use @Profile("prod") anotación para identificar la producción Registro prodDataDource en el entorno.

En este punto, ejecutamos el método testProfile01() de la clase ProfileTest y encontramos que la línea de comando no muestra la información del resultado. Explique que después de agregar anotaciones @Profile a diferentes fuentes de datos, los beans no se registrarán en el contenedor IOC de manera predeterminada. Necesitamos registrar los beans correspondientes en el contenedor IOC de acuerdo con la visualización del entorno.

En otras palabras: el bean marcado con el entorno a través de la anotación @Profile se registrará en el contenedor IOC solo cuando el entorno esté activado.

¿Qué sucede si necesitamos un entorno predeterminado?
En este punto, podemos identificar un entorno predeterminado a través de la anotación @Profile("predeterminado"). Por ejemplo, identificamos el entorno devDataSource como el entorno predeterminado, como se muestra a continuación.

@Profile("default")
@Bean("devDataSource")
public DataSource dataSourceDev() throws Exception{
    
    
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_dev");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    return dataSource;
}

En este punto, ejecutamos el método testProfile01() de la clase ProfileTest y la información de salida es la siguiente.

devDataSource

Como puede ver, usamos la anotación @Profile("default") en la fuente de datos devDataSource para establecerla como la fuente de datos predeterminada, y la línea de comando generará devDataSource al ejecutar el método de prueba.

A continuación, restauramos la anotación @Profile("default") de la fuente de datos devDataSource a la anotación @Profile("dev"), identificándola como una fuente de datos registrada en un entorno de desarrollo.

Entonces, ¿cómo registramos el bean correspondiente según los diferentes entornos?

La primera forma es determinar el entorno en función de los parámetros de la línea de comandos. Podemos agregar los parámetros de la línea de comandos correspondientes al ejecutar el programa. Por ejemplo, nuestro entorno actual es un entorno de prueba, por lo que podemos agregar los siguientes parámetros de la línea de comandos al ejecutar el programa. .

-Dspring.profiles.active=test

La segunda forma es mediante el método de construcción sin argumentos de la clase AnnotationConfigApplicationContext. Llamamos al método de construcción sin argumentos de AnnotationConfigApplicationContext en el programa para generar el contenedor IOC. Antes de inicializar el contenedor, configuramos el entorno correspondiente para el contenedor IOC y luego configuramos la clase de configuración principal para el contenedor IOC. Por ejemplo, configuramos el contenedor IOC como entorno de producción, como se muestra a continuación.

@Test
public void testProfile02(){
    
    
    //创建IOC容器
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.getEnvironment().setActiveProfiles("prod");
    context.register(ProfileConfig.class);
    context.refresh();
    String[] names = context.getBeanNamesForType(DataSource.class);
    Stream.of(names).forEach(System.out::println);
}

En este punto, ejecutamos el método testProfile02() y la información de salida es la siguiente.

prodDataDource

Se puede ver que la línea de comando genera prodDataDource, lo que indica que hemos configurado correctamente el entorno IOC en el entorno de producción.

@Profile se puede marcar no solo en los métodos, sino también en las clases de configuración. Si se marca en la clase de configuración, todas las configuraciones en toda la clase de configuración surtirán efecto solo en el entorno especificado. Por ejemplo, anotamos la anotación @Profile("dev") en la clase ProfileConfig como se muestra a continuación.

@Profile("dev")
@Configuration
public class ProfileConfig {
    
    
    /*********代码省略*********/
}

A continuación, ejecutamos el método testProfile02() y encontramos que no se muestra información en la línea de comando.

Esto se debe a que especificamos el entorno actual como entorno de producción en el método testProfile02(), y la anotación en la clase ProfileConfig es @Profile("dev"), lo que indica que todas las configuraciones en la clase ProfileConfig solo tendrán efecto en el desarrollo. medio ambiente Por lo tanto, en este momento, ninguna fuente de datos está registrada en el contenedor IOC y la línea de comando no imprimirá ninguna información.

Supongo que te gusta

Origin blog.csdn.net/qq_36602071/article/details/129874062
Recomendado
Clasificación