7.高级装配(一)

7.高级装配(一)

1. 环境与Profile

1.解决不同环境不同配置

  1. maven构建时,使用profiles来确定将哪一个配置编译到可部署的应用
    1. 缺点:不同环境重新构建,可能引入bug
  2. 使用Spring profile

2.配置方式

  1. Java

    1. 可以放在类上和方法上,类上的级别会覆盖方法上的,放在类级别上,表示该类型所有的bean都受此影响

      package com.desmond.springlearning.profiles;
      
      import com.desmond.springlearning.profiles.vo.Person;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Profile;
      
      /**
       * Created by presleyli on 2018/4/6.
       */
      @Configuration
      @Profile("dev")
      public class ConfigurationConfig {
      
          @Bean
          @Profile("prod")
          public Person getProdPerson() {
              Person person = new Person();
              person.setName("prod");
      
              return person;
          }
      
          @Bean
          public String name() {
              return "prod";
          }
      
          @Bean
          @Profile("test")
          public Person getTestPerson() {
              Person person = new Person();
              person.setName("test");
      
              return person;
          }
      
          @Bean
          @Profile("dev")
          public Person getDevPerson() {
              Person person = new Person();
              person.setName("dev");
      
              return person;
          }
      }
      
      
    2. JVM配置 参数 -Dspring.profiles.default=dev

  2. XML

    1. xml中只能放在上

    2. 代码

      <?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">
      
          <beans profile="prod">
              <bean id="person" class="com.desmond.springlearning.profiles.vo.Person">
                  <constructor-arg value="prod" />
              </bean>
          </beans>
      
          <beans profile="test">
              <bean id="testPerson" class="com.desmond.springlearning.profiles.vo.Person">
                  <constructor-arg value="test"/>
              </bean>
          </beans>
      
          <beans profile="dev">
              <bean id="devPerson" class="com.desmond.springlearning.profiles.vo.Person">
                  <constructor-arg value="dev"/>
              </bean>
          </beans>
      </beans>
      
      1. JVM配置 参数 -Dspring.profiles.default=dev

      2. 测试类

        package com.desmond.springlearning.profiles;
        
        import com.desmond.springlearning.profiles.vo.Person;
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.annotation.AnnotationConfigApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;
        
        /**
         * @author presleyli
         * @date 2018/10/9 下午10:15
         */
        public class XmlTest {
            public static void main(String[] args) {
                ApplicationContext context = new ClassPathXmlApplicationContext("profiles/config.xml");
        
                Person person = context.getBean(Person.class);
        
                System.out.println(person.getName());
            }
        }
        
        
    3. 激活 profile

      1. 须依赖两个属性 spring.profiles.active和 spring.profiles.default, 如果设置了active, 先用active;否使用default. 如果两者均未设置,则无激活的profile, 也就只加载哪些没有定义在profile里的bean.
      2. 多种方式设置这两个属性
        1. DispatcherServlet 初始化参数
        2. Web应用上下文
        3. JNDI
        4. 环境变量
        5. JVM 变量 eg. -Dspring.profiles.default=dev
        6. 在集成测试类上,使用注解 @ActiveProfiles

2. 条件化bean

1. 概念

当一个或者多个bean需要遇到特定条件才创建

2. 举例

  1. 假设当Person类,当环境中设置人名为Tom时,才认为此人标签为牛掰

  2. 首先,定义一个条件类,实现Condition接口

    package com.desmond.springlearning.conditional;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    /**
     * @author presleyli
     * @date 2018/10/9 下午10:55
     */
    public class PersonCondition implements Condition{
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            String name = conditionContext.getEnvironment().getProperty("name");
    
            return "Tom".equalsIgnoreCase(name);
        }
    }
    
    
    1. 定义configuration
    package com.desmond.springlearning.conditional;
    
    /**
     * @author presleyli
     * @date 2018/10/9 下午10:53
     */
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ConConfiguration {
        @Bean
        @Conditional(PersonCondition.class)
        public Person person() {
            Person person = new Person();
    
            person.setNotes("此人牛掰.");
    
            return person;
        }
    }
    
    
  3. Person

    package com.desmond.springlearning.conditional;
    
    import lombok.Data;
    
    /**
     * @author presleyli
     * @date 2018/10/9 下午10:52
     */
    @Data
    public class Person {
        public String notes;
    }
    
    
  4. 测试

    package com.desmond.springlearning.conditional;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    /**
     * @author presleyli
     * @date 2018/10/9 下午10:15
     */
    public class AnnoCondTest {
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(ConConfiguration.class);
    
            Person person = context.getBean(Person.class);
    
            System.out.println(person.getNotes());
        }
    }
    
    
  5. 添加环境变量 name=Tom

  6. 结果
    此人牛掰. 否则找不到bean:

    Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.desmond.springlearning.conditional.Person' available
    
  7. 从4.0 @Profile也使用此法:

    1. 注解

      //
      // Source code recreated from a .class file by IntelliJ IDEA
      // (powered by Fernflower decompiler)
      //
      
      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;
      
      @Target({ElementType.TYPE, ElementType.METHOD})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      
      @Conditional({ProfileCondition.class}) // 条件
      
      public @interface Profile {
          String[] value();
      }
      
      
    2. condition

      /*
       * Copyright 2002-2013 the original author or authors.
       *
       * Licensed under the Apache License, Version 2.0 (the "License");
       * you may not use this file except in compliance with the License.
       * You may obtain a copy of the License at
       *
       *      http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in writing, software
       * distributed under the License is distributed on an "AS IS" BASIS,
       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       * See the License for the specific language governing permissions and
       * limitations under the License.
       */
      
      package org.springframework.context.annotation;
      
      import org.springframework.core.type.AnnotatedTypeMetadata;
      import org.springframework.util.MultiValueMap;
      
      /**
       * {@link Condition} that matches based on the value of a {@link Profile @Profile}
       * annotation.
       *
       * @author Chris Beams
       * @author Phillip Webb
       * @author Juergen Hoeller
       * @since 4.0
       */
      class ProfileCondition implements Condition {
      
      	@Override
      	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
      		if (context.getEnvironment() != null) {
      			MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
      			if (attrs != null) {
      				for (Object value : attrs.get("value")) {
      					if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
      						return true;
      					}
      				}
      				return false;
      			}
      		}
      		return true;
      	}
      
      }
      
      

猜你喜欢

转载自blog.csdn.net/firemaple_li/article/details/83019472