前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springBoot学习(二)配置环境动态切换和部分注解的运用

springBoot学习(二)配置环境动态切换和部分注解的运用

作者头像
杨小杰
发布2019-07-04 16:25:50
3880
发布2019-07-04 16:25:50
举报

springBoot配置环境动态切换

建立第一个配置文件(springBoot默认读取的文件)application.properties

代码语言:javascript
复制
test.name=default
test.defaultAge=12

建立第二个配置文件(开发环境)application-dev.properties

代码语言:javascript
复制
test.name=dev
test.devAge=13

建立第三个配置文件(用户验收测试环境)application-uat.properties

代码语言:javascript
复制
test.name=uat
test.uatAge=14

1.添加启动参数(--spring.profiles.active=),测试结果读取application.properties的值

2.添加启动参数(--spring.profiles.active=dev),测试结果读取application-dev.properties的值

3.添加启动参数(--spring.profiles.active=uat),测试结果读取application-uat.properties的值

4.添加启动参数(--spring.profiles.active=uat,dev),测试结果读取application-dev.properties的值

5.添加启动参数(--spring.profiles.active=dev,uat),测试结果读取application-uat.properties的值

6.添加启动参数(--spring.profiles.active=dev),可以读到application.properties的(test.defaultAge)值,读不到uat的(test.uatAge)值。

7.添加启动参数(--spring.profiles.active=uat),可以读到application.properties的(test.defaultAge)值,读不到dev的(test.devAge)值。

8.添加启动参数(--spring.profiles.active=),可以读到application.properties的值,读取不到其他配置文件的值

重点
  • 添加启动参数--spring.profiles.active=“环境代表参数”(此值为文件名“-”与“.”中间的值,此处即为dev或者uat)
  • 可以添加多个参数,通过英文逗号(,)分割
  • 如果添加多个参数,有重复key,值会被覆盖,(配置文件加载顺序详见官方文档:24. Externalized Configuration)
  • 也可以直接在application.properties配置文件中添加spring.profiles.active=“环境代表参数” 来替代启动时候添加的参数

springBoot自动配置bean

首先看一个正常配置的bean与打印

建立一个接口

代码语言:javascript
复制
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 {
}

建立两个实现-第一个

代码语言:javascript
复制
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 {
}

建立两个实现-第二个

代码语言:javascript
复制
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

代码语言:javascript
复制
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启动类测试

代码语言:javascript
复制
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));
    }
}

测试结果

代码语言:javascript
复制
------------------分割线------------------
{createWechat=com.yxj.spring.Wechat@5cad8b7d, createPipiXia=com.yxj.spring.PipiXia@7b02e036}
可以看到结果把通过@Bean加载的两个MakeApp实现类对象全部打印出来了
了解Condition接口,实现自定义bean的加载

源代码

代码语言:javascript
复制
/*
 * 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)

代码语言:javascript
复制
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)

代码语言:javascript
复制
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注解来实现

代码语言:javascript
复制
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();
    }
}

再次测试,测试结果

代码语言:javascript
复制
------------------分割线------------------
{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注解

代码语言:javascript
复制
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注解

代码语言:javascript
复制
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));
    }
}

测试结果

代码语言:javascript
复制
------------------分割线------------------
{createPipiXia=com.yxj.spring.PipiXia@6548bb7d}
测试结果表明了,虽然配置类没有加入@SpringBootConfiguration,@Component,@Service,@Controller等交给spring管理的注解,但是通过启动类添加@Import引入方式,仍然可以在spring进行依赖注入,交由spring管理
声明
  • 本人是与springBoot教学视频同步学习,此文章是看视频与查阅各位大佬博客文章总结出来的重点内容。
  • 如果觉得文章描绘的不够清楚,欢迎留言,也可以关注公众号,在公众号内发送关键字“springboot”或者“springBoot”领取springBoot教程。
  • 排版不易,希望大家能够点点关注,共同学习,有问题请指出,谢谢大家。
  • ps:我也希望本人能够精准表达springBoot的一些重点内容,减少大家观看视频的大额时间。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA知识总结与分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • springBoot配置环境动态切换
    • 重点
      • 首先看一个正常配置的bean与打印
      • 了解Condition接口,实现自定义bean的加载
      • SpringBoot中自带的Condition实现
      • 用处
      • 测试
      • 声明
  • springBoot自动配置bean
  • @Import注解
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档