Ten, Spring of @Profile comment

First we look at spring official explanation of this document annotation:

The @Profile annotation allows you to indicate that a component is eligible for registration when one or more specified profiles are active

This notation according to the current environment, the dynamic range of the activation and switching component

Combined with some knowledge before doing an example, when we developed, may in the development of connections is the development environment of the database, when the test connection test environment, the production environment is connected is the production database, used in different environments the database is different, how to dynamically switch data sources injected it?

Configuration class to explain

First, look at the configuration class MainConfigProfileclass

import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;
import com.atguigu.bean.Yellow;
import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * Profile:
 *      Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
 * 
 * 开发环境、测试环境、生产环境;
 * 数据源:(/A)(/B)(/C);
 * 
 * 
 * @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
 * 
 * 1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
 * 2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
 * 3)、没有标注环境标识的bean在,任何环境下都是加载的;
 */

@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{
    
    @Value("${db.user}")
    private String user;
    
    private StringValueResolver valueResolver;
    
    private String  driverClass;
    
    
    @Bean
    public Yellow yellow(){
        return new Yellow();
    }
    
    @Profile("test")
    @Bean("testDataSource")
    public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); // 测试库
        dataSource.setDriverClass(driverClass);
        return dataSource;
    }
    
    
    @Profile("dev")
    @Bean("devDataSource")
    public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud"); // 开发库
        dataSource.setDriverClass(driverClass);
        return dataSource;
    }
    
    @Profile("prod")
    @Bean("prodDataSource")
    public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515");  // 生产库
        
        dataSource.setDriverClass(driverClass);
        return dataSource;
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        // TODO Auto-generated method stub
        this.valueResolver = resolver;
        driverClass = valueResolver.resolveStringValue("${db.driverClass}");
    }

}

In the configuration class, we injected three Bean, corresponding to the test environment, development environment, production environment.

We know that inject data sources need Four Diamond: user, password, driver, url.

Note: Here, the three environments that are not connected to the same database, as we are here only to distinguish url. Url in each environment is different.

The other three parameters, we are disposed in the path of the class db.propertiesas follows

db.user=root
db.password=123456
db.driverClass=com.mysql.jdbc.Driver

Prior knowledge combined with my study here, into a different use db.propertiesvalues

The use of the resource file is loaded, this usage can be found: the Spring and @PropertySource is used @Value property assignment

@PropertySource("classpath:/dbconfig.properties")

That is how

dataSource.setUser(user);
dataSource.setPassword(pwd);

These two methods of assigning it?

First we construct a

private String user;Attribute, then the attributes @Value("${db.user}")and then

dataSource.setUser(user);To get the value.

Secondly it,

public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{...}We add a parameter in the method, before adding a parameter @Value("${db.password}")can from the resource file db.propertiesto get the value, assigned to this parameter

Summary: The above is @Value usage, refer to the link above

Were here, we put it another way, to get the resource file driverClass,

We can implement EmbeddedValueResolverAwareinterfaces spring there are many aware interface is available to way we use the underlying functionality of the spring.

Here EmbeddedValueResolverAwareis the value resolver, implement the interface, which is an abstract method of achieving

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        // TODO Auto-generated method stub
        this.valueResolver = resolver;
        driverClass = valueResolver.resolveStringValue("${db.driverClass}");
    }

When the container starts, this method will be called,

We define an attribute for the value of the received process parameter, i.e.StringValueResolver resolver

private StringValueResolver valueResolver;

Then parse

driverClass = valueResolver.resolveStringValue("${db.driverClass}");

And assigned to the property driverClass our custom. So this property would get the value of the resource file

And above relationship @Profile not much, but good review

In addition, we are still in the configuration class defined called yellowthe bean.


Test, and activate the corresponding environment

First, we all do not join @Profilecomment

Test, watch the console output, which we called a test method

package com.atguigu.test;

import javax.sql.DataSource;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.atguigu.bean.Yellow;
import com.atguigu.config.MainConfigOfProfile;

public class IOCTest_Profile {

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
    }
}
mainConfigOfProfile
yellow
testDataSource
devDataSource
prodDataSource

Class contains the configuration can be seen that all of the bean itself ioc are injected into the vessel.

Now open all @Profile comments

For example, we are now devunder development environment that is, how to activate only @Bean("devDataSource")the component of it?

We write a test class

package com.atguigu.test;

import javax.sql.DataSource;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.atguigu.bean.Yellow;
import com.atguigu.config.MainConfigOfProfile;

public class IOCTest_Profile {
    
    //1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test
    @SuppressWarnings("resource")
    //2、代码的方式激活某种环境;
    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = 
                new AnnotationConfigApplicationContext();
        //1、创建一个applicationContext
        //2、设置需要激活的环境
        applicationContext.getEnvironment().setActiveProfiles("dev");   // 这里可以写多个值,
        //3、注册主配置类
        applicationContext.register(MainConfigOfProfile.class);
        //4、启动刷新容器
        applicationContext.refresh();
        
        
        String[] namesForType = applicationContext.getBeanNamesForType(DataSource.class);
        for (String string : namesForType) {
            System.out.println(string);
        }
        
        Yellow bean = applicationContext.getBean(Yellow.class);
        System.out.println(bean);
        applicationContext.close();
        
//      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
//      String[] definitionNames = applicationContext.getBeanDefinitionNames();
//      for (String name : definitionNames) {
//          System.out.println(name);
//      }
    
    }

}

Print Console:

devDataSource
com.atguigu.bean.Yellow@27ce24aa // 没有被@Profile修饰。

Observation can be found, indeed, only development environment bean is injected ioc container,


There is another way to activate @Profile comment.

Test Method 1:

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
    }

Then run the process, but parameters need to add virtual machines running time. We need to activate the back = environment, a plurality of values ​​separated by commas.

-Dspring.profiles.active=test

Print it out:

mainConfigOfProfile
yellow
testDataSource //测试环境被注入

@Profile annotation at the class,

Remain unchanged configuration class, we add on the configuration class@Profile("prod")

We run the test method (preceded mentioned), and not the console output, which represents the configuration of the bean class have not been injected into the container,

May be thinking this way: @Profile notes marked on the class, if you do not specify an activation of the environment, the natural configuration of the entire class will not be loaded, configured class Bean (even if, as Yellow, not @Profile notes), nor It will be injected into the container,

In the same way that we have to correct the environment after it is activated? (How to activate the environment, refer to the previous article)

Console printout

mainConfigOfProfile
yellow
prodDataSource

This is obviously what we expected is the same.


Tips

If the environment is not activated, it @Profile("default")will be activated, that is, the default is the default setting.

Guess you like

Origin www.cnblogs.com/heliusKing/p/11409498.html