SpringBoot配置環境動態切換
創建第一個配置文件(springBoot默認讀取的文件)application.propertiesphp
test.name=default
test.defaultAge=12
創建第二個配置文件(開發環境)application-dev.propertiesjava
test.name=dev
test.devAge=13
創建第三個配置文件(用戶驗收測試環境)application-uat.propertiesspring
test.name=uat
test.uatAge=14
1.添加啓動參數(--spring.profiles.active=),測試結果讀取application.properties的值express
2.添加啓動參數(--spring.profiles.active=dev),測試結果讀取application-dev.properties的值apache
3.添加啓動參數(--spring.profiles.active=uat),測試結果讀取application-uat.properties的值springboot
4.添加啓動參數(--spring.profiles.active=uat,dev),測試結果讀取application-dev.properties的值微信
5.添加啓動參數(--spring.profiles.active=dev,uat),測試結果讀取application-uat.properties的值app
6.添加啓動參數(--spring.profiles.active=dev),能夠讀到application.properties的(test.defaultAge)值,讀不到uat的(test.uatAge)值。less
7.添加啓動參數(--spring.profiles.active=uat),能夠讀到application.properties的(test.defaultAge)值,讀不到dev的(test.devAge)值。ide
8.添加啓動參數(--spring.profiles.active=),能夠讀到application.properties的值,讀取不到其餘配置文件的值
重點
添加啓動參數--spring.profiles.active=「環境表明參數」(此值爲文件名「-」與「.」中間的值,此處即爲dev或者uat)
能夠添加多個參數,經過英文逗號(,)分割
若是添加多個參數,有重複key,值會被覆蓋,(配置文件加載順序詳見官方文檔:24. Externalized Configuration)
也能夠直接在application.properties配置文件中添加spring.profiles.active=「環境表明參數」 來替代啓動時候添加的參數
springBoot自動配置bean
首先看一個正常配置的bean與打印
創建一個接口
package com.yxj.spring;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description:
* @Author: 阿杰
* @CreateDate: 2019/1/22 22:08
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/22 22:08
* @UpdateRemark: The modified content
* @Version: 1.0
*/
public interface MakeApp {
}
創建兩個實現-第一個
package com.yxj.spring;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description:
* @Author: 阿杰
* @CreateDate: 2019/1/22 22:13
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/22 22:13
* @UpdateRemark: The modified content
* @Version: 1.0
*/
public class Wechat implements MakeApp {
}
創建兩個實現-第二個
package com.yxj.spring;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description:
* @Author: 阿杰
* @CreateDate: 2019/1/22 22:14
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/22 22:14
* @UpdateRemark: The modified content
* @Version: 1.0
*/
public class PipiXia implements MakeApp {
}
經過@SpringBootConfiguration與@Bean加載bean
package com.yxj.spring;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description: @SpringBootConfiguration繼承自@Configuration,
* 兩者功能也一致,標註當前類是配置類,
* 並會將當前類內聲明的一個或多個以@Bean註解標記的方法的實例歸入到spring容器中,
* 而且實例名就是方法名。
* @Author: 阿杰
* @CreateDate: 2019/1/22 22:14
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/22 22:14
* @UpdateRemark: The modified content
* @Version: 1.0
*/
@SpringBootConfiguration
public class LoadMyBean {
@Bean
public MakeApp createWechat(){
return new Wechat();
}
@Bean
public MakeApp createPipiXia(){
return new PipiXia();
}
}
springBoot啓動類測試
package com.yxj.spring;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import java.util.List;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description:
* @Author: 楊小杰
* @CreateDate: 2019/1/18 20:18
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/18 20:18
* @UpdateRemark: The modified content
* @Version: 1.0
*/
@SpringBootApplication
public class SpringBootTestRun {
/**
* getBeansOfType(MakeApp.class)會裝配bean類型是MakeApp的全部實例
* @param args
*/
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(SpringBootTestRun.class, args);
System.out.println("------------------分割線------------------");
System.out.println(run.getBeansOfType(MakeApp.class));
}
}
測試結果
------------------分割線------------------
{createWechat=com.yxj.spring.Wechat@5cad8b7d, createPipiXia=com.yxj.spring.PipiXia@7b02e036}
能夠看到結果把經過@Bean加載的兩個MakeApp實現類對象所有打印出來了
瞭解Condition接口,實現自定義bean的加載
源代碼
/*
* Copyright 2002-2017 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.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* A single {@code condition} that must be {@linkplain #matches matched} in order
* for a component to be registered.
*
* <p>Conditions are checked immediately before the bean-definition is due to be
* registered and are free to veto registration based on any criteria that can
* be determined at that point.
*
* <p>Conditions must follow the same restrictions as {@link BeanFactoryPostProcessor}
* and take care to never interact with bean instances. For more fine-grained control
* of conditions that interact with {@code @Configuration} beans consider the
* {@link ConfigurationCondition} interface.
*
* @author Phillip Webb
* @since 4.0
* @see ConfigurationCondition
* @see Conditional
* @see ConditionContext
*/
@FunctionalInterface
public interface Condition {
/**
* Determine if the condition matches.
* @param context the condition context
* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
* or {@link org.springframework.core.type.MethodMetadata method} being checked
* @return {@code true} if the condition matches and the component can be registered,
* or {@code false} to veto the annotated component's registration
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
上訴代碼描述了matches返回值若是是ture就會再加bean,反之則反
實現自定義Condition
新建Wechat自定義Condition,默認返回false(不裝配bean)
package com.yxj.spring;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description:
* @Author: 阿杰
* @CreateDate: 2019/1/22 22:35
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/22 22:35
* @UpdateRemark: The modified content
* @Version: 1.0
*/
public class WechatCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
新建PipiXia自定義Condition,默認返回true(裝配bean)
package com.yxj.spring;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description:
* @Author: 阿杰
* @CreateDate: 2019/1/22 22:35
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/22 22:35
* @UpdateRemark: The modified content
* @Version: 1.0
*/
public class PipiXiaCondition implements Condition {
/**
*當name不爲空的時候,判斷若是name中包含appName的時候返回true
* @param context
* @param metadata
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
在@Bean所在的類中添加自定義條件,配合@Conditional註解來實現
package com.yxj.spring;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description: @SpringBootConfiguration繼承自@Configuration,
* 兩者功能也一致,標註當前類是配置類,
* 並會將當前類內聲明的一個或多個以@Bean註解標記的方法的實例歸入到spring容器中,
* 而且實例名就是方法名。
* @Author: 阿杰
* @CreateDate: 2019/1/22 22:14
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/22 22:14
* @UpdateRemark: The modified content
* @Version: 1.0
*/
@SpringBootConfiguration
public class LoadMyBean {
@Bean
@Conditional(WechatCondition.class)
public MakeApp createWechat(){
return new Wechat();
}
@Bean
@Conditional(PipiXiaCondition.class)
public MakeApp createPipiXia(){
return new PipiXia();
}
}
再次測試,測試結果
------------------分割線------------------
{createPipiXia=com.yxj.spring.PipiXia@420bc288}
能夠看到只打印了一個pipixia實例bean,微信沒有裝配進來
SpringBoot中自帶的Condition實現
能夠看到這個是繼承了@Conditional註解,傳了自定義的class對象,變成了一個新的註解
經常使用@Conditional註解使用,能夠查看大佬博客https://blog.csdn.net/u012437781/article/details/78626617
@Import註解
用處
@Import其實就是引入一個或多個配置,能夠導入普通類,也能夠導入配置類(上述的LoadMyBean爲配置類,主要經過@Bean生成bean給spring管理)
@Import用來導入一個或多個類(會被spring容器管理),或者配置類(配置類裏的@Bean標記的類也會被spring容器管理)
測試
仍是以上的例子,去掉配置類(LoadMyBean)中的@SpringBootConfiguration註解
package com.yxj.spring;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description: @SpringBootConfiguration繼承自@Configuration,
* 兩者功能也一致,標註當前類是配置類,
* 並會將當前類內聲明的一個或多個以@Bean註解標記的方法的實例歸入到spring容器中,
* 而且實例名就是方法名。
* @Author: 阿杰
* @CreateDate: 2019/1/22 22:14
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/22 22:14
* @UpdateRemark: The modified content
* @Version: 1.0
*/
public class LoadMyBean {
@Bean
@Conditional(WechatCondition.class)
public MakeApp createWechat(){
return new Wechat();
}
@Bean
@Conditional(PipiXiaCondition.class)
public MakeApp createPipiXia(){
return new PipiXia();
}
}
修改springboot啓動類,添加@Import註解
package com.yxj.spring;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.*;
import java.util.List;
/**
* @ProjectName: springBootDemo
* @Package: com.yxj.spring
* @Description:
* @Author: 楊小杰
* @CreateDate: 2019/1/18 20:18
* @UpdateUser: 暫無
* @UpdateDate: 2019/1/18 20:18
* @UpdateRemark: The modified content
* @Version: 1.0
*/
@SpringBootApplication
@Import(LoadMyBean.class)
public class SpringBootTestRun {
/**
* getBeansOfType(MakeApp.class)會裝配bean類型是MakeApp的全部實例
* @param args
*/
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(SpringBootTestRun.class, args);
System.out.println("------------------分割線------------------");
System.out.println(run.getBeansOfType(MakeApp.class));
}
}
測試結果
------------------分割線------------------
{createPipiXia=com.yxj.spring.PipiXia@6548bb7d}
測試結果代表了,雖然配置類沒有加入@SpringBootConfiguration,@Component,@Service,@Controller等交給spring管理的註解,可是經過啓動類添加@Import引入方式,仍然能夠在spring進行依賴注入,交由spring管理
若是你感受文章對你有幫助,就掃描二維碼關注我吧!
長按識別二維碼,瞭解更多
掃描二維碼加入技術交流羣!
本文分享自微信公衆號 - 亂敲代碼(lqcoder)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。