1. 程式人生 > >25、自動裝配[email protected]根據環境註冊bean

25、自動裝配[email protected]根據環境註冊bean

25、自動裝配[email protected]根據環境註冊bean

  • 指定元件在哪個環境的情況下才能被註冊到容器中
  • 加了環境標識的,只有這個環境被啟用才能註冊到元件中
  • 預設是default環境
  • 寫在類上,整個配置類的啟用的時候才能生效
  • 沒有標註環境標識的bean,在任何環境下都是載入的
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 {

    /**
     * 指定元件在哪個環境的情況下才能被註冊到容器中
     * The set of profiles for which the annotated component should be registered.
     */
    String[] value();

}

25.1 實現

package com.hw.springannotation.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * @Description Profile
 * @Author hw
 * @Date 2018/11/29 19:25
 * @Version 1.0
 */
@Component
@PropertySource(value = {"classpath:/datasource.properties"})
public class MainConfigOfProfile implements EmbeddedValueResolverAware {

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

    private String driveClassName;

    private StringValueResolver resolver;

    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
        this.driveClassName = this.resolver.resolveStringValue("${db.driveClassName}");
    }

    @Profile("default")
    @Bean
    public DataSource dataSourceTest(@Value("${db.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(username);
        dataSource.setPassword(password);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setDriverClass(driveClassName);
        return dataSource;
    }

    @Profile("dev")
    @Bean
    public DataSource dataSourceDev(@Value("${db.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(username);
        dataSource.setPassword(password);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mysql");
        dataSource.setDriverClass(driveClassName);
        return dataSource;
    }

    @Profile("prod")
    @Bean
    public DataSource dataSourceProd(@Value("${db.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(username);
        dataSource.setPassword(password);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/qm_dmp");
        dataSource.setDriverClass(driveClassName);
        return dataSource;
    }
}

執行:

25.2 切換環境-使用命令列動態引數

  • 在執行時指定
-Dspring.profiles.active=prod

25.3 切換環境-使用程式碼的方式

  • 之前使用的是有參構造器,配置載入完,容器就重新整理了,所以使用無參構造器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        this();
        register(annotatedClasses);
        refresh();
    }

步驟

  1. 構造IOC容器
  2. 設定需要啟用的環境
  3. 注入配置類
  4. 啟動重新整理容器
@Test
public void test() {
    // 1. 構造IOC容器
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    // 2. 設定需要啟用的環境(可以同時啟用多個)
    applicationContext.getEnvironment().setActiveProfiles("test", "dev");
    // 3. 注入配置類
    applicationContext.register(MainConfigOfProfile.class);
    // 4. 啟動重新整理容器
    applicationContext.refresh();

    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
        System.out.println(name);
    }

}