diff --git a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java index a77d70202ad..71591ef9ef8 100644 --- a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java +++ b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java @@ -63,19 +63,20 @@ public final class HttpServiceProxyFactory { private final @Nullable StringValueResolver embeddedValueResolver; - private final List proxyCustomizers; + private final List proxyFactoryCustomizers; + private HttpServiceProxyFactory( HttpExchangeAdapter exchangeAdapter, List argumentResolvers, List requestValuesProcessor, @Nullable StringValueResolver embeddedValueResolver, - List proxyCustomizers) { + List proxyFactoryCustomizers) { this.exchangeAdapter = exchangeAdapter; this.argumentResolvers = argumentResolvers; this.requestValuesProcessor = new CompositeHttpRequestValuesProcessor(requestValuesProcessor); this.embeddedValueResolver = embeddedValueResolver; - this.proxyCustomizers = proxyCustomizers; + this.proxyFactoryCustomizers = proxyFactoryCustomizers; } @@ -99,7 +100,7 @@ public final class HttpServiceProxyFactory { private S getProxy(Class serviceType, List httpServiceMethods) { MethodInterceptor interceptor = new HttpServiceMethodInterceptor(httpServiceMethods); ProxyFactory factory = new ProxyFactory(serviceType, interceptor); - for (var customizer : this.proxyCustomizers) { + for (ProxyFactoryCustomizer customizer : this.proxyFactoryCustomizers) { customizer.customize(factory, serviceType); } return (S) factory.getProxy(serviceType.getClassLoader()); @@ -152,7 +153,7 @@ public final class HttpServiceProxyFactory { private @Nullable StringValueResolver embeddedValueResolver; - private final List proxyCustomizers = new ArrayList<>(); + private final List proxyFactoryCustomizers = new ArrayList<>(); private Builder() { } @@ -224,15 +225,14 @@ public final class HttpServiceProxyFactory { } /** - * Register an {@link ProxyFactoryCustomizer} that can - * manipulating the {@link ProxyFactory} before creating proxy. - * + * Register a callback to customize the {@link ProxyFactory} used to + * create the proxy for each HTTP service interface. * @param customizer the customizer to add * @return this same builder instance * @since 7.1 */ - public Builder proxyCustomizer(ProxyFactoryCustomizer customizer) { - this.proxyCustomizers.add(customizer); + public Builder proxyFactoryCustomizer(ProxyFactoryCustomizer customizer) { + this.proxyFactoryCustomizers.add(customizer); return this; } @@ -245,7 +245,7 @@ public final class HttpServiceProxyFactory { return new HttpServiceProxyFactory( adapterToUse, initArgumentResolvers(), this.requestValuesProcessors, - this.embeddedValueResolver, this.proxyCustomizers); + this.embeddedValueResolver, this.proxyFactoryCustomizers); } @SuppressWarnings({"DataFlowIssue", "NullAway"}) @@ -334,17 +334,20 @@ public final class HttpServiceProxyFactory { } /** - * Callback interface used during HttpService proxy creation. Allows manipulating the {@link ProxyFactory} creating the - * HttpService. - * + * Callback mechanism to customize the {@link ProxyFactory} used to create the + * proxy for each HTTP service interface, e.g. to add AOP interceptors. * @author Dung Dang Minh + * @since 7.1 */ public interface ProxyFactoryCustomizer { + /** - * Manipulates the {@link ProxyFactory}, e.g. add further interceptors to it. - * - * @param factory will never be {@literal null}. + * Customize the {@link ProxyFactory} for the given HTTP service type. + * @param proxyFactory will never be {@literal null}. + * @param serviceType the HTTP service interface type */ - void customize(ProxyFactory factory, Class serviceType); + void customize(ProxyFactory proxyFactory, Class serviceType); + } + } diff --git a/spring-web/src/test/java/org/springframework/web/service/invoker/HttpServiceProxyFactoryTests.java b/spring-web/src/test/java/org/springframework/web/service/invoker/HttpServiceProxyFactoryTests.java index e28a57fb625..75c3e6f731f 100644 --- a/spring-web/src/test/java/org/springframework/web/service/invoker/HttpServiceProxyFactoryTests.java +++ b/spring-web/src/test/java/org/springframework/web/service/invoker/HttpServiceProxyFactoryTests.java @@ -19,6 +19,7 @@ package org.springframework.web.service.invoker; import org.aopalliance.intercept.MethodInterceptor; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; + import org.springframework.core.ParameterizedTypeReference; import org.springframework.web.service.annotation.GetExchange; @@ -43,19 +44,19 @@ public class HttpServiceProxyFactoryTests { assertThat(service.execute()).isEqualTo("decorated"); } - @Test void proxyFactoryCustomizer() { - var mi = (MethodInterceptor) invocation -> "intercepted"; - var factory = HttpServiceProxyFactory.builderFor(mock(HttpExchangeAdapter.class)) - .proxyCustomizer((fact, serviceType) -> { - fact.addAdvice(0, mi); - }).build(); - - var service = factory.createClient(Service.class); - assertThat(service.execute()).isEqualTo("intercepted"); + var interceptor = (MethodInterceptor) invocation -> "intercepted"; + var proxyFactory = HttpServiceProxyFactory.builderFor(mock(HttpExchangeAdapter.class)) + .proxyFactoryCustomizer((factory, serviceType) -> factory.addAdvice(0, interceptor)) + .build(); + + String result = proxyFactory.createClient(Service.class).execute(); + + assertThat(result).isEqualTo("intercepted"); } + private interface Service { @GetExchange