一、为什么会想到定义@SpringCloudProfile这样的注解

首页提一下@Profile注解:它主要用与Spring Boot多环境配置中,指定某个类只在指定环境中生效,比如swagger的配置只允许开发和测试环境开发,线上需要禁止使用。

使用@Profile进行如下配置:

@Configuration
@EnableSwagger2
@Profile({"dev", "test"})
public class Swagger2Config { @Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
//当前包路径
.apis(RequestHandlerSelectors.basePackage("com.zbq.springbootbase.controller"))
.paths(PathSelectors.any()).build(); } //构建api文档的详细信息函数
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
//页面标题
.title("springboot-base-frame,使用Swagger2构建RESTful API")
//创建人
.contact(new Contact("张波清", "756623607@qq.com", ""))
//版本号
.version("1.0")
//描述
.description("API 描述")
.build(); } }

但是在Spring Cloud中由于使用了配置中心,导致启动项目时没有指定spring.profiles.active属性导致@Profile注解失效,原因就是@Profile通过获取环境变量中spring.profiles.active属性值,与注解中设置的值进行比较,包含就生效。

所有在Spring Cloud中需要换一个环境变量来实现,正好有spring.cloud.config.profile这个变量,该变量用于指定读取配置中心那个环境配置的,一般有这些值,dev、test、prod

二、自定义@SpringCloudProfile注解的实现

1)定义@SpringCloudProfile注解

/**
* @author zhangboqing
* @date 2019/11/12
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(SpringCloudProfileCondition.class)
public @interface SpringCloudProfile { /**
* The set of profiles for which the annotated component should be registered.
*/
String[] value(); }

2)实现SpringCloudProfileCondition类,用于条件匹配

/**
* @author zhangboqing
* @date 2019/11/12
*/
public class SpringCloudProfileCondition implements Condition { public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.cloud.config.profile"; @Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(SpringCloudProfile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (acceptsProfiles(context,(String[]) value)) {
return true;
}
}
return false;
}
return true;
} public boolean acceptsProfiles(ConditionContext context,String... profiles) {
Assert.notEmpty(profiles, "Must specify at least one profile");
for (String profile : profiles) {
if (StringUtils.hasLength(profile) && profile.charAt() == '!') {
if (!isProfileActive(context,profile.substring())) {
return true;
}
}
else if (isProfileActive(context,profile)) {
return true;
}
}
return false;
} protected boolean isProfileActive(ConditionContext context,String profile) {
validateProfile(profile);
String property = context.getEnvironment().getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
return property.equals(profile);
} protected void validateProfile(String profile) {
if (!StringUtils.hasText(profile)) {
throw new IllegalArgumentException("Invalid profile [" + profile + "]: must contain text");
}
if (profile.charAt() == '!') {
throw new IllegalArgumentException("Invalid profile [" + profile + "]: must not begin with ! operator");
}
}
}

最新文章

  1. 一切Web的基础----HTTP
  2. 【翻译二十一】java-并发之分拆和合并
  3. LinkedList源码分析
  4. 常用的 SQL 函数
  5. [转]WEB开发者必备的7个JavaScript函数
  6. Hibernate--Enum类型的set集合映射到数据库(xml配置文件实现方式)
  7. 关于PYTHON_EGG_CACHE无权限的问题
  8. Python基础:1.数据类型(列表)
  9. 判断IMEI或MEID是否合法
  10. pytest自动化7:assert断言
  11. 【Java入门提高篇】Day30 Java容器类详解(十二)TreeMap详解
  12. C# 列出进程
  13. Https 忽略证书\使用自定义证书的java代码实现
  14. tmux 快捷操作
  15. C#系列之{流和序列化}
  16. WPF加载HTML、WPF与JavaScript交互
  17. The import XXX cannot be resolved
  18. JAVA 之 多态 抽象 接口
  19. docker中使用nginx容器代理其他容器
  20. ssvm和console 模板机 连接不上管理节点

热门文章

  1. LeetCode 100. Same Tree相同的树 (C++)
  2. 使用jQuery的replaceWith()方法要注意的地方
  3. 洛谷 P1919 A*B Problem升级版
  4. 总线宽度VS总线带宽
  5. [LeetCode] 119. Pascal&#39;s Triangle II 杨辉三角之二
  6. java byte[]和base64互相转换
  7. vue.js三种安装方式
  8. python运维开发常用模块(三)DNS处理模块dnspython
  9. ThinkPHP连接Oracle数据库的详细教程
  10. Navicat Premium 12 安装与激活