美文网首页JAVA学习记录JavaJava 杂谈
《Spring实战》-第三章:Bean的高级装配(1)-环境Pr

《Spring实战》-第三章:Bean的高级装配(1)-环境Pr

作者: 廖小明的赖胖子 | 来源:发表于2019-03-16 21:19 被阅读0次

    慢慢来比较快,虚心学技术

    1.为什么需要profile?

    实际开发中,生产环境和开发环境通常都不会是同一个,最明显的例子就是,生产环境(正式环境)的数据库和开发环境的数据库一般都是不一样的。那么为了方便配置的转换,Spring提供了profile关键字进行统一的环境配置,通过profile配置我们可以快速的切换整个应用的环境,而不需要从代码层面进行重新构建

    那么,使用profile的目的是为了更方便的配置不同的环境,指定某些具体的类或组件的作用域

    注:每个bean或组件都有默认的作用域default,如果没有限定作用域,则这些bean都会被装配,如果指定了作用域,则只有处在相应作用域(环境)中时才会被装配

    2.怎么配置profile?

    JavaConfig显式装配或者自动装配可以通过注解@Profile进行环境限制,比如:

    Ⅰ、自动化装配,我们将类DataSource的作用域限定为只有当环境为“prod”才被装配,结合@Component注解和@Profile注解实现

    代码1.1
    
    @Component
    @Profile("prod")
    public class DataSource {
    
        /**
         * 定义名称
         */
        private String name;
    
        public DataSource(){
            super();
        }
    
        public DataSource(String name){
           this.name = name;
        }
    }
    

    Ⅱ、JavaConfig显式配置,有两种实现方式

    • 第一种:在指定多个配置类,在配置类上指定作用域,其内所定义的所有Bean只能在该作用域下被装配,进行环境统一配置
    代码1.2
    
    //1.创建一个配置类DevConfig,并将其作用域设置为dev,则其内定义的Bean只有在环境为dev的时候才可以被装载
    @Configuration
    @Profile(value = "dev")
    public class DevConfig {
    
        //定义一个name属性为Dev DataSource的Bean
        @Bean
        public DataSource dataSource(){
            return new DataSource("Dev DataSource");
        }
    }
    
    //2.创建一个配置类ProdConfig,并将其作用域设置为prod,则其内定义的Bean只有在环境为prod的时候才可以被装载
    @Configuration
    @Profile(value = "prod")
    public class ProdConfig {
    
        //定义一个name属性为Dev DataSource的Bean
        @Bean
        public DataSource dataSource(){
            return new DataSource("Prod DataSource");
        }
    }
    
    //3.创建一个默认配置类,当系统未指定系统环境时,将默认使用该配置
    @Configuration
    public class DefaultConfig {
        @Bean
        public DataSource dataSource(){
            return new DataSource("Default DataSource");
        }
    }
    
    //4.创建一个统一配置类SystemConfig,并将三个配置类引入,因为各自定义了作用域(DefaultConfig未明文指定),所以引入并不会导致冲突
    @Configuration
    @Import({DevConfig.class,ProdConfig.class,DefaultConfig.class})
    public class SystemConfig {}
    
    • 第二种:除了在类上使用@Profile指定类作用域之外,@Profile还可以在方法上使用,在JavaConfig结合@Bean进行装配环境的限制
    代码1.3
    
    @Configuration
    public class SystemConfig {
    
        @Bean
        @Profile("dev")//当系统环境为dev的时候,使用该Bean方法进行装配
        public DataSource devDataSource(){
            return new DataSource("Dev DataSource");
        }
    
        @Bean
        @Profile("prod")//当系统环境为prod的时候,使用该Bean方法进行装配
        public DataSource prodDataSource(){
            return new DataSource("Prod DataSource");
        }
    
        @Bean//默认装配
        public DataSource defaultDataSource(){
            return new DataSource("Default DataSource");
        }
    }
    

    Ⅲ、XML配置Profile,和JavaConfig类似也有两种方式

    • 第一种:为每一个配置文件的<beans>配置Profile,只有在固定对应环境下配置文件才会生效(比较常用)
    代码1.4
    
    //1、创建配置文件DevConfig.xml,并在<beans>节点设置profile属性为dev,只有在环境为dev的时候本配置文件生效
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
       profile="dev"
        >
        <bean class="com.my.spring.bean.DataSource" name="dataSource">
            <constructor-arg name="name" value="Dev DataSource"></constructor-arg>
       </bean>
    </beans>
    
    //2、创建配置文件ProdConfig.xml,并在<beans>节点设置profile属性为prod,只有在环境为prod的时候本配置文件生效
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
       profile="prod"
         >
        <bean class="com.my.spring.bean.DataSource" name="dataSource">
            <constructor-arg name="name" value="Prod DataSource"></constructor-arg>
        </bean>
    </beans>
    
    //3、创建配置文件DefaultConfig.xml,默认加载
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean class="com.my.spring.bean.DataSource" name="dataSource">
            <constructor-arg name="name" value="Default DataSource"></constructor-arg>
        </bean>
    
    </beans>
    
    //4、创建系统配置文件,将上述三个配置文件引入,因为限定了环境,所以并不会冲突
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <import resource="DefaultConfig.xml"/>
        <import resource="DevConfig.xml"/>
        <import resource="ProdConfig.xml"/>
    </beans>
    
    • 第二种:在同一个配置文件中指定不同的<beans>设定profile属性,所包裹的bean只有在指定环境下才会被装配
    代码1.5
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <description>Spring配置文件</description>
    
        <beans>
            <bean id="dataSource" name="default" class="com.my.spring.bean.DataSource">
                <constructor-arg name="name" value="Default DataSource"></constructor-arg>
            </bean>
        </beans>
    
        <beans profile="dev">
            <bean id="dataSource" name = "dev" class="com.my.spring.bean.DataSource">
                <constructor-arg name="name" value="Dev DataSource"></constructor-arg>
            </bean>
        </beans>
    
        <beans profile="prod">
            <bean id="dataSource"  name="prod" class="com.my.spring.bean.DataSource">
                <constructor-arg name="name" value="Prod DataSource"></constructor-arg>
            </bean>
        </beans>
    </beans>
    

    3、如何激活profile?

    如上述配置每个配置文件或者JavaConfig,Bean等的profile属性后,如何设定一个系统所处的环境呢?

    Spring提供了多种方式:

    作为 DispatcherServlet 的初始化参数;

    作为 Web 应用的上下文参数;

    作为 JNDI 条目;

    作为环境变量;

    作为 JVM 的系统属性;

    在集成测试类上,使用 @ActiveProfiles 注解设置;

    • 此处先了解@ActiveProfiles注解方式

    在上一章中,我们了解到,Spring测试使用@RunWith(SpringJUnit4ClassRunner.class)和@ContextConfiguration注解进行应用上下文注入测试,在测试中我们可以通过结合@ActiveProfiles注解进行测试环境的配置,具体代码如下:

    以自动化装配模式为例:

    上述代码1.1中指定DataSource只有在prod环境下才会被装载,故在测试中将系统环境分别指定为prod和dev测试DataSource的Bean是否会装配

    代码1.6
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {ComponentConfig.class})
    @ActiveProfiles("prod")//指定系统环境为prod
    public class AppComponentTest {
    
        @Autowired
        private ApplicationContext applicationContext;
    
        @Test
        public void testGetBean(){
            String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    
            for(String  beanName : beanDefinitionNames){
                System.out.println(beanName);
            }
        }
    }
    
    测试结果:
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    componentConfig
    dataSource //dataSource被装配
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {ComponentConfig.class})
    @ActiveProfiles("dev")//指定系统环境为dev
    public class AppComponentTest {
    
        @Autowired
        private ApplicationContext applicationContext;
    
        @Test
        public void testGetBean(){
            String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    
            for(String  beanName : beanDefinitionNames){
                System.out.println(beanName);
            }
        }
    }
    
    //dataSource未被装配
    测试结果:
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    componentConfig
    

    再以JavaConfig显式装配为例,设定不同的profile测试获取到的dataSource是否一致,以代码1.3作为系统配置:

    代码1.7
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {SystemConfig.class})
    @ActiveProfiles("prod")//指定系统配置环境为prod
    public class AppConfigTest {
    
        @Autowired
        private ApplicationContext applicationContext;
        @Test
        public void testGetBean(){
            String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    
            for(String  beanName : beanDefinitionNames){
                System.out.println(beanName);
            }
        }
    }
    
    测试结果:
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    systemConfig
    prodDataSource //证明获取的是prod环境的dataSource
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {SystemConfig.class})
    @ActiveProfiles("dev")//指定系统配置环境为dev
    public class AppConfigTest {
    
        @Autowired
        private ApplicationContext applicationContext;
        @Test
        public void testGetBean(){
            String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    
            for(String  beanName : beanDefinitionNames){
                System.out.println(beanName);
            }
        }
    }
    
    测试结果:
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    systemConfig
    devDataSource //证明获取的是dev环境的dataSource
    
    • 由于未了解到网络模块,所以web配置方式暂不赘述

    相关文章

      网友评论

        本文标题:《Spring实战》-第三章:Bean的高级装配(1)-环境Pr

        本文链接:https://www.haomeiwen.com/subject/woremqtx.html