From e4cd6d3337947ce80ee6ef1213b086cc452336cd Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Mon, 30 Jan 2023 12:56:18 +0100 Subject: [PATCH] Fix registration of hints for Configurables conditional on classes. (#2849) --- ...onfigurableHintsRegistrationProcessor.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/ConfigurableHintsRegistrationProcessor.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/ConfigurableHintsRegistrationProcessor.java index c10b0f51..3dab2333 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/ConfigurableHintsRegistrationProcessor.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/ConfigurableHintsRegistrationProcessor.java @@ -17,7 +17,9 @@ package org.springframework.cloud.gateway.config; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -32,6 +34,12 @@ import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContrib import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.JsonToGrpcGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.SpringCloudCircuitBreakerResilience4JFilterFactory; +import org.springframework.cloud.gateway.filter.factory.TokenRelayGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.cache.LocalResponseCacheGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter; import org.springframework.cloud.gateway.support.Configurable; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.ResolvableType; @@ -51,6 +59,26 @@ class ConfigurableHintsRegistrationProcessor implements BeanFactoryInitializatio private static final String ROOT_GATEWAY_PACKAGE_NAME = "org.springframework.cloud.gateway"; + private static final Set circuitBreakerConditionalClasses = Set.of( + "org.springframework.web.reactive.DispatcherHandler", + "org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JAutoConfiguration", + "org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory", + "org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JCircuitBreakerFactory"); + + private static final Map, Set> beansConditionalOnClasses = Map.of( + TokenRelayGatewayFilterFactory.class, + Set.of("org.springframework.security.oauth2.client.OAuth2AuthorizedClient", + "org.springframework.security.web.server.SecurityWebFilterChain", + "org.springframework.boot.autoconfigure.security.SecurityProperties"), + JsonToGrpcGatewayFilterFactory.class, Set.of("io.grpc.Channel"), RedisRateLimiter.class, + Set.of("org.springframework.data.redis.core.RedisTemplate", + "org.springframework.web.reactive.DispatcherHandler"), + SpringCloudCircuitBreakerResilience4JFilterFactory.class, circuitBreakerConditionalClasses, + FallbackHeadersGatewayFilterFactory.class, circuitBreakerConditionalClasses, + LocalResponseCacheGatewayFilterFactory.class, + Set.of("com.github.benmanes.caffeine.cache.Weigher", "com.github.benmanes.caffeine.cache.Caffeine", + "org.springframework.cache.caffeine.CaffeineCacheManager")); + @Override public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { return (generationContext, beanFactoryInitializationCode) -> { @@ -86,7 +114,9 @@ class ConfigurableHintsRegistrationProcessor implements BeanFactoryInitializatio Class clazz; try { clazz = Class.forName(component.getBeanClassName()); - classesToAdd.add(clazz); + if (shouldRegisterClass(clazz)) { + classesToAdd.add(clazz); + } } catch (NoClassDefFoundError | ClassNotFoundException exception) { if (LOG.isDebugEnabled()) { @@ -97,4 +127,17 @@ class ConfigurableHintsRegistrationProcessor implements BeanFactoryInitializatio return classesToAdd; } + private static boolean shouldRegisterClass(Class clazz) { + Set conditionClasses = beansConditionalOnClasses.getOrDefault(clazz, Collections.emptySet()); + for (String conditionClass : conditionClasses) { + try { + ConfigurableHintsRegistrationProcessor.class.getClassLoader().loadClass(conditionClass); + } + catch (ClassNotFoundException e) { + return false; + } + } + return true; + } + }