[spring annotation driven development] - auto assembly - @ Profile

Posted by GroundZeroStudio on Sun, 08 Mar 2020 06:49:43 +0100

Article directory

Source address of demo of this blog
https://github.com/suchahaerkang/spring-annotation.git

The role of @ profile

@Function of Profile: switch between different environments, and register different components to the container dynamically
Now there is a requirement. We all know that when we develop a project, we usually have development (dev), test (test) and production (prod) environments. The data sources of each environment are different. Now how can we only switch the environment and register the corresponding components to the container dynamically?
Let's start with the code
First, we introduce the package of data source into the project. Here we use c3p0. Then introduce a mysql driver package

<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
	<groupId>c3p0</groupId>
	<artifactId>c3p0</artifactId>
	<version>0.9.1.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.44</version>
</dependency>

Write a configuration class to register three components in the container (develop data source devDataSource, test data source testDataSource, generate data source prodDataSource)

/**
 * @description:
 * @author: sukang
 * @date: 2020-03-08 12:40
 */
@PropertySource(value = {"classpath:/db.properties"})
@Configuration
public class MainConfigOfProfile {

    @Value("${database.username}")
    private String userName;

    @Value("${database.password}")
    private String password;

    @Value("${database.driver}")
    private String driver;

    @Bean("devDataSource")
    public DataSource dataSourceOfDev() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("http://localhost:3306/dev");
        dataSource.setUser(userName);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driver);
        return dataSource;
    }

    @Bean("testDataSource")
    public DataSource dataSourceOfTest() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("http://localhost:3306/test");
        dataSource.setUser(userName);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driver);
        return dataSource;
    }

    @Bean("prodDataSource")
    public DataSource dataSourceOfProd() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("http://localhost:3306/prod");
        dataSource.setUser(userName);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driver);
        return dataSource;
    }
}

By default, all three data sources will be registered in the container
Write a test case

@Test
public void test01(){
    //Create container
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
    //Get all the names of the components in the container as DataSource
    String[] beanNames = applicationContext.getBeanNamesForType(DataSource.class);

    for (String name : beanNames) {
        System.out.println(name);
    }
}

Operation result

The test results show that all three data sources are registered in the container, but this is not what we want. We want to register what kind of data sources in what kind of environment. Next, we use the @ Profile annotation to implement this function, plus the @ Profile annotation's configuration class

/**
 * @description:
 * @author: sukang
 * @date: 2020-03-08 12:40
 */
@PropertySource(value = {"classpath:/db.properties"})
@Configuration
public class MainConfigOfProfile {

    @Value("${database.username}")
    private String userName;

    @Value("${database.password}")
    private String password;

    @Value("${database.driver}")
    private String driver;

    @Profile("dev")
    @Bean("devDataSource")
    public DataSource dataSourceOfDev() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev");
        dataSource.setUser(userName);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driver);
        return dataSource;
    }

    @Profile("test")
    @Bean("testDataSource")
    public DataSource dataSourceOfTest() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUser(userName);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driver);
        return dataSource;
    }

    @Profile("prod")
    @Bean("prodDataSource")
    public DataSource dataSourceOfProd() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/prod");
        dataSource.setUser(userName);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driver);
        return dataSource;
    }
}

After adding @ Profile to the configuration class, it has no effect. You must activate an environment when starting the container to take effect

2 two ways to activate the environment

1) Using command line dynamic parameters, add '- Dspring.profiles.active=dev' to the virtual machine parameter location

Operation result

2) Another way is by writing code

@Test
public void test02(){
    //Create container call parameterless constructor
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    //Activate test environment
    applicationContext.getEnvironment().setActiveProfiles("test");
    //Register MainConfigOfProfile component
    applicationContext.register(MainConfigOfProfile.class);
    //Refresh container
    applicationContext.refresh();

    //Get all the names of the components in the container as DataSource
    String[] beanNames = applicationContext.getBeanNamesForType(DataSource.class);

    for (String name : beanNames) {
        System.out.println(name);
    }
}

Operation result

78 original articles published, 32 praised, 90000 visitors+
Private letter follow

Topics: MySQL Database JDBC Java