Spring: How to do AND in Profiles?

前端 未结 7 1595
太阳男子
太阳男子 2020-12-25 10:40

Spring Profile annotation allows you to select profiles. However if you read documentation it only allows you to select more than one profile with OR operation. If you speci

7条回答
  •  清酒与你
    2020-12-25 11:09

    I improved @rozhoc's answer since that answer did not account for the fact that no profile is equivalent to 'default' when it comes to using @Profile. Also, conditions that I wanted were !default && !a which @rozhoc's code did not handle properly. Finally I used some Java8 and show only the matches method for brevity.

    @Override
    public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
        if (context.getEnvironment() == null) {
            return true;
        }
        MultiValueMap attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
        if (attrs == null) {
            return true;
        }
    
        Set activeProfilesSet = Arrays.stream(context.getEnvironment().getActiveProfiles()).collect(Collectors.toSet());
        String[] definedProfiles = (String[]) attrs.getFirst(VALUE);
        Set allowedProfiles = new HashSet<>(1);
        Set restrictedProfiles = new HashSet<>(1);
        if (activeProfilesSet.size() == 0) {
            activeProfilesSet.add(DEFAULT_PROFILE);  // no profile is equivalent in @Profile terms to "default"
        }
        for (String nextDefinedProfile : definedProfiles) {
            if (!nextDefinedProfile.isEmpty() && nextDefinedProfile.charAt(0) == '!') {
                restrictedProfiles.add(nextDefinedProfile.substring(1, nextDefinedProfile.length()));
                continue;
            }
            allowedProfiles.add(nextDefinedProfile);
        }
        boolean allowed = true;
        for (String allowedProfile : allowedProfiles) {
            allowed = allowed && activeProfilesSet.contains(allowedProfile);
        }
        boolean restricted = true;
        for (String restrictedProfile : restrictedProfiles) {
            restricted = restricted && !activeProfilesSet.contains(restrictedProfile);
        }
        return allowed && restricted;
    }
    

    Here is how you actually use it in case that was confusing as well:

    @Profile({"!default", "!a"})
    @Conditional(value={AndProfilesCondition.class})
    

提交回复
热议问题