test prod example baeldung active java spring spring-profiles

java - example - spring profiles active prod



Primavera: ¿Cómo hacer Y en Perfiles? (6)

Dado que Spring no proporciona la función AND de fábrica. Sugeriría la siguiente estrategia:

Actualmente, la anotación @Profile tiene una anotación condicional @Conditional(ProfileCondition.class) . En ProfileCondition.class itera a través de los perfiles y comprueba si el perfil está activo. De forma similar, puede crear su propia implementación condicional y restringir el registro del bean. p.ej

public class MyProfileCondition implements Condition { @Override public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) { if (context.getEnvironment() != null) { final MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); if (attrs != null) { for (final Object value : attrs.get("value")) { final String activeProfiles = context.getEnvironment().getProperty("spring.profiles.active"); for (final String profile : (String[]) value) { if (!activeProfiles.contains(profile)) { return false; } } } return true; } } return true; } }

En tu clase:

@Component @Profile("dev") @Conditional(value = { MyProfileCondition.class }) public class DevDatasourceConfig

NOTA: No he verificado todos los casos de esquina (como nulo, verificaciones de longitud, etc.). Pero, esta dirección podría ayudar.

La anotación de Spring Profile permite seleccionar perfiles. Sin embargo, si lee la documentación, solo le permite seleccionar más de un perfil con la operación OR. Si especifica @Perfil ("A", "B"), su bean estará activo si el perfil A o el perfil B están activos.

Nuestro caso de uso es diferente, queremos apoyar las versiones TEST y PROD de múltiples configuraciones. Por lo tanto, a veces queremos autorizar automáticamente el bean si ambos perfiles TEST y CONFIG1 están activos.

¿Hay alguna manera de hacerlo con Spring? ¿Cuál sería la manera más simple?


Mejoré la respuesta de @ rozhoc ya que esa respuesta no tuvo en cuenta el hecho de que ningún perfil es equivalente a ''predeterminado'' cuando se trata de usar @Profile. Además, las condiciones que quería eran !default && !a que el código de @ rozhoc no manejaba correctamente. Finalmente, utilicé algo de Java8 y muestro solo el método de concordancia por brevedad.

@Override public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) { if (context.getEnvironment() == null) { return true; } MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); if (attrs == null) { return true; } Set<String> activeProfilesSet = Arrays.stream(context.getEnvironment().getActiveProfiles()).collect(Collectors.toSet()); String[] definedProfiles = (String[]) attrs.getFirst(VALUE); Set<String> allowedProfiles = new HashSet<>(1); Set<String> 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; }

Así es como realmente lo usa en caso de que también sea confuso:

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


Otra opción más es jugar en el nivel de Clase / Método permitido por la anotación @Profile . No es tan flexible como implementar MyProfileCondition pero es rápido y limpio si se ajusta a su caso.

por ejemplo, esto no se iniciará cuando FAST y DEV estén activos, pero si solo DEV es:

@Configuration @Profile("!" + SPRING_PROFILE_FAST) public class TomcatLogbackAccessConfiguration { @Bean @Profile({SPRING_PROFILE_DEVELOPMENT, SPRING_PROFILE_STAGING}) public EmbeddedServletContainerCustomizer containerCustomizer() {


Otro tipo de truco pero que podría funcionar en muchos escenarios es colocar la anotación @Profile en @Configuration y la otra @Profile en @Bean - que crea un AND lógico entre 2 perfiles en la configuración Spring basada en Java.

@Configuration @Profile("Profile1") public class TomcatLogbackAccessConfiguration { @Bean @Profile("Profile2") public EmbeddedServletContainerCustomizer containerCustomizer() {


Si ya ha marcado una clase de configuración o un método de bean con la anotación @Profile, es sencillo verificar los perfiles adicionales (por ejemplo, para la condición AND) con Environment.acceptsProfiles()

@Autowired Environment env; @Profile("profile1") @Bean public MyBean myBean() { if( env.acceptsProfiles("profile2") ) { return new MyBean(); } else { return null; } }


Un poco mejorada versión de @Mithun respuesta:

public class AndProfilesCondition implements Condition { public static final String VALUE = "value"; public static final String DEFAULT_PROFILE = "default"; @Override public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) { if (context.getEnvironment() == null) { return true; } MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); if (attrs == null) { return true; } String[] activeProfiles = context.getEnvironment().getActiveProfiles(); String[] definedProfiles = (String[]) attrs.getFirst(VALUE); Set<String> allowedProfiles = new HashSet<>(1); Set<String> restrictedProfiles = new HashSet<>(1); for (String nextDefinedProfile : definedProfiles) { if (!nextDefinedProfile.isEmpty() && nextDefinedProfile.charAt(0) == ''!'') { restrictedProfiles.add(nextDefinedProfile.substring(1, nextDefinedProfile.length())); continue; } allowedProfiles.add(nextDefinedProfile); } int activeAllowedCount = 0; for (String nextActiveProfile : activeProfiles) { // quick exit when default profile is active and allowed profiles is empty if (DEFAULT_PROFILE.equals(nextActiveProfile) && allowedProfiles.isEmpty()) { continue; } // quick exit when one of active profiles is restricted if (restrictedProfiles.contains(nextActiveProfile)) { return false; } // just go ahead when there is no allowed profiles (just need to check that there is no active restricted profiles) if (allowedProfiles.isEmpty()) { continue; } if (allowedProfiles.contains(nextActiveProfile)) { activeAllowedCount++; } } return activeAllowedCount == allowedProfiles.size(); } }

No se pudo publicar en los comentarios.