1. 程式人生 > >7.高階裝配(一)

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;
      	}
      
      }