【Spring Cloud】Spring Cloud之自定义@SpringCloudProfile注解实现@Profile注解的功能

一、为什么会想到定义@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(0) == '!') {
                if (!isProfileActive(context,profile.substring(1))) {
                    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(0) == '!') {
            throw new IllegalArgumentException("Invalid profile [" + profile + "]: must not begin with ! operator");
        }
    }
}

 

posted @ 2019-11-12 23:33  N!CE波  阅读(1418)  评论(0编辑  收藏  举报