From b1b5f41821783c8e7c87bc161c794118c8e53a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=88=98=ED=98=84?= Date: Mon, 12 Jun 2023 13:19:56 +0900 Subject: [PATCH 1/6] Change BeanPostProcessor to InstantiationAwareBeanPostProcessor in GrpcClientBeanPostProcessor --- .../inject/GrpcClientBeanPostProcessor.java | 163 ++++++++++++++++-- 1 file changed, 148 insertions(+), 15 deletions(-) diff --git a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java index ab638b8a6..5d3f78cd8 100644 --- a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java +++ b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java @@ -19,27 +19,46 @@ import static java.util.Objects.requireNonNull; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.annotation.PostConstruct; import org.springframework.beans.BeanInstantiationException; +import org.springframework.beans.BeanUtils; import org.springframework.beans.BeansException; import org.springframework.beans.InvalidPropertyException; +import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; +import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; +import org.springframework.core.BridgeMethodResolver; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.core.annotation.MergedAnnotations; +import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import com.google.common.collect.Lists; @@ -51,6 +70,7 @@ import net.devh.boot.grpc.client.nameresolver.NameResolverRegistration; import net.devh.boot.grpc.client.stubfactory.FallbackStubFactory; import net.devh.boot.grpc.client.stubfactory.StubFactory; +import org.springframework.util.StringUtils; /** * This {@link BeanPostProcessor} searches for fields and methods in beans that are annotated with {@link GrpcClient} @@ -59,7 +79,7 @@ * @author Michael (yidongnan@gmail.com) * @author Daniel Theuke (daniel.theuke@heuboe.de) */ -public class GrpcClientBeanPostProcessor implements BeanPostProcessor { +public class GrpcClientBeanPostProcessor implements InstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor { private final ApplicationContext applicationContext; @@ -72,14 +92,20 @@ public class GrpcClientBeanPostProcessor implements BeanPostProcessor { // For bean registration via @GrpcClientBean private ConfigurableListableBeanFactory configurableBeanFactory; + private final Set> grpcClientAnnotationTypes = new LinkedHashSet<>(4); + + private final Map injectionMetadataCache = new ConcurrentHashMap<>(256); + /** - * Creates a new GrpcClientBeanPostProcessor with the given ApplicationContext. + * Creates a new GrpcClientBeanPostProcessor with the given ApplicationContext + * for GrpcClient standard {@link GrpcClient @GrpcClient} annotation. * * @param applicationContext The application context that will be used to get lazy access to the * {@link GrpcChannelFactory} and {@link StubTransformer}s. */ public GrpcClientBeanPostProcessor(final ApplicationContext applicationContext) { this.applicationContext = requireNonNull(applicationContext, "applicationContext"); + this.grpcClientAnnotationTypes.add(GrpcClient.class); } @PostConstruct @@ -119,19 +145,18 @@ private void initGrpClientConstructorInjections() { } @Override - public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException { - Class clazz = bean.getClass(); - do { - processFields(clazz, bean); - processMethods(clazz, bean); - - if (isAnnotatedWithConfiguration(clazz)) { - processGrpcClientBeansAnnotations(clazz); - } - - clazz = clazz.getSuperclass(); - } while (clazz != null); - return bean; + public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { + InjectionMetadata metadata = findGrpcClientMetadata(beanName, bean.getClass(), pvs); + try { + metadata.inject(bean, beanName, pvs); + } + catch (BeanCreationException ex) { + throw ex; + } + catch (Throwable ex) { + throw new BeanCreationException(beanName, "Injection of gRPC client stub failed", ex); + } + return pvs; } /** @@ -400,4 +425,112 @@ private boolean isAnnotatedWithConfiguration(final Class clazz) { return configurationAnnotation != null; } + @Override + public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { + InjectionMetadata metadata = findGrpcClientMetadata(beanName, beanType, null); + metadata.checkConfigMembers(beanDefinition); + } + + private InjectionMetadata findGrpcClientMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) { + // Fall back to class name as cache key, for backwards compatibility with custom callers. + String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); + // Quick check on the concurrent map first, with minimal locking. + InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); + if (InjectionMetadata.needsRefresh(metadata, clazz)) { + synchronized (this.injectionMetadataCache) { + metadata = this.injectionMetadataCache.get(cacheKey); + if (InjectionMetadata.needsRefresh(metadata, clazz)) { + if (metadata != null) { + metadata.clear(pvs); + } + metadata = buildGrpcClientMetadata(clazz); + this.injectionMetadataCache.put(cacheKey, metadata); + } + } + } + return metadata; + } + + private InjectionMetadata buildGrpcClientMetadata(Class clazz) { + if (!AnnotationUtils.isCandidateClass(clazz, this.grpcClientAnnotationTypes)) { + return InjectionMetadata.EMPTY; + } + + List elements = new ArrayList<>(); + Class targetClass = clazz; + + do { + final List currElements = new ArrayList<>(); + + ReflectionUtils.doWithLocalFields(targetClass, field -> { + MergedAnnotation ann = findGrpcClientAnnotation(field); + if (ann != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("GrpcClient annotation is not supported on static fields: " + field); + } + currElements.add(new GrpcClientMemberElement(field, null)); + } + }); + + ReflectionUtils.doWithLocalMethods(targetClass, method -> { + Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { + return; + } + MergedAnnotation ann = findGrpcClientAnnotation(bridgedMethod); + if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("GrpcClient annotation is not supported on static method: " + method); + } + if (method.getParameterCount() == 0) { + throw new IllegalStateException("GrpcClient annotation should only be used on methods with parameters: " + method); + } + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); + currElements.add(new GrpcClientMemberElement(method, pd)); + } + }); + + elements.addAll(0, currElements); + targetClass = targetClass.getSuperclass(); + } + while (targetClass != null && targetClass != Object.class); + + return InjectionMetadata.forElements(elements, clazz); + } + + private MergedAnnotation findGrpcClientAnnotation(AccessibleObject ao) { + MergedAnnotations annotations = MergedAnnotations.from(ao); + for (Class type : this.grpcClientAnnotationTypes) { + MergedAnnotation annotation = annotations.get(type); + if (annotation.isPresent()) { + return annotation; + } + } + return null; + } + + /** + * Class representing injection information about an annotated member. + */ + private class GrpcClientMemberElement extends InjectionMetadata.InjectedElement { + + public GrpcClientMemberElement(Member member, @Nullable PropertyDescriptor pd) { + super(member, pd); + } + + @Override + protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { + Class clazz = bean.getClass(); + do { + processFields(clazz, bean); + processMethods(clazz, bean); + + if (isAnnotatedWithConfiguration(clazz)) { + processGrpcClientBeansAnnotations(clazz); + } + + clazz = clazz.getSuperclass(); + } while (clazz != null); + } + } } From 5e4b477bdaec55c8e037f2df50b51b1035253de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=88=98=ED=98=84?= Date: Mon, 12 Jun 2023 17:44:36 +0900 Subject: [PATCH 2/6] Missing Bean Registration for @GrpcClientBean --- .../inject/GrpcClientBeanPostProcessor.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java index 5d3f78cd8..033e56f96 100644 --- a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java +++ b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java @@ -144,6 +144,19 @@ private void initGrpClientConstructorInjections() { } } + @Override + public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException { + Class clazz = bean.getClass(); + do { + if (isAnnotatedWithConfiguration(clazz)) { + processGrpcClientBeansAnnotations(clazz); + } + + clazz = clazz.getSuperclass(); + } while (clazz != null); + return bean; + } + @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findGrpcClientMetadata(beanName, bean.getClass(), pvs); @@ -525,10 +538,6 @@ protected void inject(Object bean, @Nullable String beanName, @Nullable Property processFields(clazz, bean); processMethods(clazz, bean); - if (isAnnotatedWithConfiguration(clazz)) { - processGrpcClientBeansAnnotations(clazz); - } - clazz = clazz.getSuperclass(); } while (clazz != null); } From 4c26935d2673fc6b702821af6bcaded3eb2f05ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=88=98=ED=98=84?= Date: Fri, 16 Jun 2023 18:09:28 +0900 Subject: [PATCH 3/6] Add LoadTimeWeaverAware and test --- .../GrpcClientAutoConfiguration.java | 17 ++++ .../inject/GrpcClientBeanPostProcessor.java | 8 +- .../test/inject/GrpcClientMetricsTest.java | 91 +++++++++++++++++++ 3 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java diff --git a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java index 88411e3e4..bbbb8f199 100644 --- a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java +++ b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.List; +import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -52,6 +53,8 @@ import net.devh.boot.grpc.client.stubfactory.BlockingStubFactory; import net.devh.boot.grpc.client.stubfactory.FutureStubFactory; import net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration; +import org.springframework.context.weaving.LoadTimeWeaverAware; +import org.springframework.instrument.classloading.LoadTimeWeaver; /** * The auto configuration used by Spring-Boot that contains all beans to create and inject grpc clients into beans. @@ -194,4 +197,18 @@ GrpcChannelFactory inProcessGrpcChannelFactory( return new InProcessChannelFactory(properties, globalClientInterceptorRegistry, channelConfigurers); } + @Configuration(proxyBeanMethods = false) + static class GrpcClientConstructorInjectionConfiguration implements LoadTimeWeaverAware { + @Autowired + private GrpcClientBeanPostProcessor grpcClientBeanPostProcessor; + + @PostConstruct + public void init() { + grpcClientBeanPostProcessor.initGrpClientConstructorInjections(); + } + + @Override + public void setLoadTimeWeaver(LoadTimeWeaver ltw) { + } + } } diff --git a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java index 033e56f96..fe6a93a46 100644 --- a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java +++ b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.PostConstruct; import org.springframework.beans.BeanInstantiationException; import org.springframework.beans.BeanUtils; @@ -108,15 +107,10 @@ public GrpcClientBeanPostProcessor(final ApplicationContext applicationContext) this.grpcClientAnnotationTypes.add(GrpcClient.class); } - @PostConstruct - public void init() { - initGrpClientConstructorInjections(); - } - /** * Triggers registering grpc client beans from GrpcClientConstructorInjection. */ - private void initGrpClientConstructorInjections() { + public void initGrpClientConstructorInjections() { Iterable registries; try { registries = getConfigurableBeanFactory().getBean(GrpcClientConstructorInjection.class).getRegistries(); diff --git a/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java b/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java new file mode 100644 index 000000000..6209cb88b --- /dev/null +++ b/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java @@ -0,0 +1,91 @@ +package net.devh.boot.grpc.test.inject; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +import io.grpc.stub.AbstractStub; +import io.micrometer.core.instrument.MeterRegistry; +import net.devh.boot.grpc.client.inject.GrpcClient; +import net.devh.boot.grpc.client.stubfactory.StandardJavaGrpcStubFactory; +import net.devh.boot.grpc.client.stubfactory.StubFactory; +import net.devh.boot.grpc.test.config.BaseAutoConfiguration; +import net.devh.boot.grpc.test.config.InProcessConfiguration; +import net.devh.boot.grpc.test.config.MetricConfiguration; +import net.devh.boot.grpc.test.config.ServiceConfiguration; +import net.devh.boot.grpc.test.proto.TestServiceGrpc; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.autoconfigure.metrics.JvmMetricsAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +@SpringBootTest +@SpringJUnitConfig( + classes = { + GrpcClientMetricsTest.TestConfig.class, + GrpcClientMetricsTest.GrpcClientConstructorInjectionBean.class, + InProcessConfiguration.class, + ServiceConfiguration.class, + BaseAutoConfiguration.class, + MetricConfiguration.class + }) +@DirtiesContext +public class GrpcClientMetricsTest { + @Autowired + MeterRegistry registry; + + @Test + void jvmMetricsTest() { + assertThat(registry.getMeters()) + .filteredOn(meter -> meter.getId().getName().contains("jvm")) + .isNotEmpty(); + } + + @Component + public static class GrpcClientConstructorInjectionBean { + public TestServiceGrpc.TestServiceBlockingStub blockingStub; + public TestServiceGrpc.TestServiceFutureStub futureStubForClientTest; + public TestServiceGrpc.TestServiceBlockingStub anotherBlockingStub; + public TestServiceGrpc.TestServiceBlockingStub unnamedTestServiceBlockingStub; + public CustomGrpc.FactoryMethodAccessibleStub anotherServiceClientBean; + + public GrpcClientConstructorInjectionBean( + @GrpcClient("test") TestServiceGrpc.TestServiceBlockingStub blockingStub, + @GrpcClient("test") TestServiceGrpc.TestServiceFutureStub futureStubForClientTest, + @GrpcClient("anotherTest") TestServiceGrpc.TestServiceBlockingStub anotherBlockingStub, + @GrpcClient("unnamed") TestServiceGrpc.TestServiceBlockingStub unnamedTestServiceBlockingStub, + @GrpcClient("test") CustomGrpc.FactoryMethodAccessibleStub anotherServiceClientBean) { + this.blockingStub = blockingStub; + this.futureStubForClientTest = futureStubForClientTest; + this.anotherBlockingStub = anotherBlockingStub; + this.unnamedTestServiceBlockingStub = unnamedTestServiceBlockingStub; + this.anotherServiceClientBean = anotherServiceClientBean; + } + } + + @Configuration + @ImportAutoConfiguration({MetricsAutoConfiguration.class, JvmMetricsAutoConfiguration.class}) + public static class TestConfig { + @Bean + StubFactory customStubFactory() { + return new StandardJavaGrpcStubFactory() { + + @Override + public boolean isApplicable(final Class> stubType) { + return CustomStub.class.isAssignableFrom(stubType); + } + + @Override + protected String getFactoryMethodName() { + return "custom"; + } + + }; + } + } +} From eb84d2c2a95ffe2f2cc7ae6e3bdb1eb79ee2f5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=88=98=ED=98=84?= Date: Mon, 19 Jun 2023 13:47:31 +0900 Subject: [PATCH 4/6] Code Formatting --- .../GrpcClientAutoConfiguration.java | 17 ++-- .../inject/GrpcClientBeanPostProcessor.java | 28 +++--- .../test/inject/GrpcClientMetricsTest.java | 86 +++++++++++-------- 3 files changed, 73 insertions(+), 58 deletions(-) diff --git a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java index bbbb8f199..35f725eec 100644 --- a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java +++ b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java @@ -21,6 +21,7 @@ import java.util.List; import javax.annotation.PostConstruct; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -31,6 +32,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; +import org.springframework.context.weaving.LoadTimeWeaverAware; +import org.springframework.instrument.classloading.LoadTimeWeaver; import io.grpc.CompressorRegistry; import io.grpc.DecompressorRegistry; @@ -53,8 +56,6 @@ import net.devh.boot.grpc.client.stubfactory.BlockingStubFactory; import net.devh.boot.grpc.client.stubfactory.FutureStubFactory; import net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration; -import org.springframework.context.weaving.LoadTimeWeaverAware; -import org.springframework.instrument.classloading.LoadTimeWeaver; /** * The auto configuration used by Spring-Boot that contains all beans to create and inject grpc clients into beans. @@ -153,8 +154,7 @@ List defaultChannelConfigurers() { "io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder"}) @Bean @Lazy - GrpcChannelFactory shadedNettyGrpcChannelFactory( - final GrpcChannelsProperties properties, + GrpcChannelFactory shadedNettyGrpcChannelFactory(final GrpcChannelsProperties properties, final GlobalClientInterceptorRegistry globalClientInterceptorRegistry, final List channelConfigurers) { @@ -171,8 +171,7 @@ GrpcChannelFactory shadedNettyGrpcChannelFactory( @ConditionalOnClass(name = {"io.netty.channel.Channel", "io.grpc.netty.NettyChannelBuilder"}) @Bean @Lazy - GrpcChannelFactory nettyGrpcChannelFactory( - final GrpcChannelsProperties properties, + GrpcChannelFactory nettyGrpcChannelFactory(final GrpcChannelsProperties properties, final GlobalClientInterceptorRegistry globalClientInterceptorRegistry, final List channelConfigurers) { @@ -188,8 +187,7 @@ GrpcChannelFactory nettyGrpcChannelFactory( @ConditionalOnMissingBean(GrpcChannelFactory.class) @Bean @Lazy - GrpcChannelFactory inProcessGrpcChannelFactory( - final GrpcChannelsProperties properties, + GrpcChannelFactory inProcessGrpcChannelFactory(final GrpcChannelsProperties properties, final GlobalClientInterceptorRegistry globalClientInterceptorRegistry, final List channelConfigurers) { @@ -208,7 +206,6 @@ public void init() { } @Override - public void setLoadTimeWeaver(LoadTimeWeaver ltw) { - } + public void setLoadTimeWeaver(LoadTimeWeaver ltw) {} } } diff --git a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java index fe6a93a46..5bb264ca8 100644 --- a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java +++ b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java @@ -30,7 +30,6 @@ import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; - import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -59,6 +58,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; import com.google.common.collect.Lists; @@ -69,7 +69,6 @@ import net.devh.boot.grpc.client.nameresolver.NameResolverRegistration; import net.devh.boot.grpc.client.stubfactory.FallbackStubFactory; import net.devh.boot.grpc.client.stubfactory.StubFactory; -import org.springframework.util.StringUtils; /** * This {@link BeanPostProcessor} searches for fields and methods in beans that are annotated with {@link GrpcClient} @@ -78,7 +77,8 @@ * @author Michael (yidongnan@gmail.com) * @author Daniel Theuke (daniel.theuke@heuboe.de) */ -public class GrpcClientBeanPostProcessor implements InstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor { +public class GrpcClientBeanPostProcessor + implements InstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor { private final ApplicationContext applicationContext; @@ -96,8 +96,8 @@ public class GrpcClientBeanPostProcessor implements InstantiationAwareBeanPostPr private final Map injectionMetadataCache = new ConcurrentHashMap<>(256); /** - * Creates a new GrpcClientBeanPostProcessor with the given ApplicationContext - * for GrpcClient standard {@link GrpcClient @GrpcClient} annotation. + * Creates a new GrpcClientBeanPostProcessor with the given ApplicationContext for GrpcClient standard + * {@link GrpcClient @GrpcClient} annotation. * * @param applicationContext The application context that will be used to get lazy access to the * {@link GrpcChannelFactory} and {@link StubTransformer}s. @@ -156,11 +156,9 @@ public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, Str InjectionMetadata metadata = findGrpcClientMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); - } - catch (BeanCreationException ex) { + } catch (BeanCreationException ex) { throw ex; - } - catch (Throwable ex) { + } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of gRPC client stub failed", ex); } return pvs; @@ -473,7 +471,8 @@ private InjectionMetadata buildGrpcClientMetadata(Class clazz) { MergedAnnotation ann = findGrpcClientAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { - throw new IllegalStateException("GrpcClient annotation is not supported on static fields: " + field); + throw new IllegalStateException( + "GrpcClient annotation is not supported on static fields: " + field); } currElements.add(new GrpcClientMemberElement(field, null)); } @@ -487,10 +486,12 @@ private InjectionMetadata buildGrpcClientMetadata(Class clazz) { MergedAnnotation ann = findGrpcClientAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { - throw new IllegalStateException("GrpcClient annotation is not supported on static method: " + method); + throw new IllegalStateException( + "GrpcClient annotation is not supported on static method: " + method); } if (method.getParameterCount() == 0) { - throw new IllegalStateException("GrpcClient annotation should only be used on methods with parameters: " + method); + throw new IllegalStateException( + "GrpcClient annotation should only be used on methods with parameters: " + method); } PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new GrpcClientMemberElement(method, pd)); @@ -499,8 +500,7 @@ private InjectionMetadata buildGrpcClientMetadata(Class clazz) { elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); - } - while (targetClass != null && targetClass != Object.class); + } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); } diff --git a/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java b/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java index 6209cb88b..26ec959fe 100644 --- a/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java +++ b/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java @@ -1,17 +1,24 @@ +/* + * Copyright (c) 2016-2023 Michael Zhang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + package net.devh.boot.grpc.test.inject; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; -import io.grpc.stub.AbstractStub; -import io.micrometer.core.instrument.MeterRegistry; -import net.devh.boot.grpc.client.inject.GrpcClient; -import net.devh.boot.grpc.client.stubfactory.StandardJavaGrpcStubFactory; -import net.devh.boot.grpc.client.stubfactory.StubFactory; -import net.devh.boot.grpc.test.config.BaseAutoConfiguration; -import net.devh.boot.grpc.test.config.InProcessConfiguration; -import net.devh.boot.grpc.test.config.MetricConfiguration; -import net.devh.boot.grpc.test.config.ServiceConfiguration; -import net.devh.boot.grpc.test.proto.TestServiceGrpc; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.autoconfigure.metrics.JvmMetricsAutoConfiguration; @@ -24,16 +31,27 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import io.grpc.stub.AbstractStub; +import io.micrometer.core.instrument.MeterRegistry; +import net.devh.boot.grpc.client.inject.GrpcClient; +import net.devh.boot.grpc.client.stubfactory.StandardJavaGrpcStubFactory; +import net.devh.boot.grpc.client.stubfactory.StubFactory; +import net.devh.boot.grpc.test.config.BaseAutoConfiguration; +import net.devh.boot.grpc.test.config.InProcessConfiguration; +import net.devh.boot.grpc.test.config.MetricConfiguration; +import net.devh.boot.grpc.test.config.ServiceConfiguration; +import net.devh.boot.grpc.test.proto.TestServiceGrpc; + @SpringBootTest @SpringJUnitConfig( - classes = { - GrpcClientMetricsTest.TestConfig.class, - GrpcClientMetricsTest.GrpcClientConstructorInjectionBean.class, - InProcessConfiguration.class, - ServiceConfiguration.class, - BaseAutoConfiguration.class, - MetricConfiguration.class - }) + classes = { + GrpcClientMetricsTest.TestConfig.class, + GrpcClientMetricsTest.GrpcClientConstructorInjectionBean.class, + InProcessConfiguration.class, + ServiceConfiguration.class, + BaseAutoConfiguration.class, + MetricConfiguration.class + }) @DirtiesContext public class GrpcClientMetricsTest { @Autowired @@ -42,8 +60,8 @@ public class GrpcClientMetricsTest { @Test void jvmMetricsTest() { assertThat(registry.getMeters()) - .filteredOn(meter -> meter.getId().getName().contains("jvm")) - .isNotEmpty(); + .filteredOn(meter -> meter.getId().getName().contains("jvm")) + .isNotEmpty(); } @Component @@ -55,16 +73,16 @@ public static class GrpcClientConstructorInjectionBean { public CustomGrpc.FactoryMethodAccessibleStub anotherServiceClientBean; public GrpcClientConstructorInjectionBean( - @GrpcClient("test") TestServiceGrpc.TestServiceBlockingStub blockingStub, - @GrpcClient("test") TestServiceGrpc.TestServiceFutureStub futureStubForClientTest, - @GrpcClient("anotherTest") TestServiceGrpc.TestServiceBlockingStub anotherBlockingStub, - @GrpcClient("unnamed") TestServiceGrpc.TestServiceBlockingStub unnamedTestServiceBlockingStub, - @GrpcClient("test") CustomGrpc.FactoryMethodAccessibleStub anotherServiceClientBean) { - this.blockingStub = blockingStub; - this.futureStubForClientTest = futureStubForClientTest; - this.anotherBlockingStub = anotherBlockingStub; - this.unnamedTestServiceBlockingStub = unnamedTestServiceBlockingStub; - this.anotherServiceClientBean = anotherServiceClientBean; + @GrpcClient("test") TestServiceGrpc.TestServiceBlockingStub blockingStub, + @GrpcClient("test") TestServiceGrpc.TestServiceFutureStub futureStubForClientTest, + @GrpcClient("anotherTest") TestServiceGrpc.TestServiceBlockingStub anotherBlockingStub, + @GrpcClient("unnamed") TestServiceGrpc.TestServiceBlockingStub unnamedTestServiceBlockingStub, + @GrpcClient("test") CustomGrpc.FactoryMethodAccessibleStub anotherServiceClientBean) { + this.blockingStub = blockingStub; + this.futureStubForClientTest = futureStubForClientTest; + this.anotherBlockingStub = anotherBlockingStub; + this.unnamedTestServiceBlockingStub = unnamedTestServiceBlockingStub; + this.anotherServiceClientBean = anotherServiceClientBean; } } @@ -77,13 +95,13 @@ StubFactory customStubFactory() { @Override public boolean isApplicable(final Class> stubType) { - return CustomStub.class.isAssignableFrom(stubType); - } + return CustomStub.class.isAssignableFrom(stubType); + } @Override protected String getFactoryMethodName() { - return "custom"; - } + return "custom"; + } }; } From e7979985e00bda3cc505168a8168c815798161a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=88=98=ED=98=84?= Date: Wed, 22 Nov 2023 17:44:33 +0900 Subject: [PATCH 5/6] Code Formatting --- .../GrpcClientAutoConfiguration.java | 3 +-- .../inject/GrpcClientBeanPostProcessor.java | 1 - .../test/inject/GrpcClientMetricsTest.java | 21 +++++++++---------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java index 784009ebc..9cc48ae5e 100644 --- a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java +++ b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java @@ -19,8 +19,6 @@ import java.util.Collections; import java.util.List; -import javax.annotation.PostConstruct; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -38,6 +36,7 @@ import io.grpc.DecompressorRegistry; import io.grpc.NameResolverProvider; import io.grpc.NameResolverRegistry; +import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import net.devh.boot.grpc.client.channelfactory.GrpcChannelConfigurer; import net.devh.boot.grpc.client.channelfactory.GrpcChannelFactory; diff --git a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java index 9d48f7754..9b646f0a2 100644 --- a/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java +++ b/grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/inject/GrpcClientBeanPostProcessor.java @@ -64,7 +64,6 @@ import io.grpc.Channel; import io.grpc.ClientInterceptor; import io.grpc.stub.AbstractStub; -import jakarta.annotation.PostConstruct; import net.devh.boot.grpc.client.channelfactory.GrpcChannelFactory; import net.devh.boot.grpc.client.nameresolver.NameResolverRegistration; import net.devh.boot.grpc.client.stubfactory.FallbackStubFactory; diff --git a/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java b/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java index 26ec959fe..420f94748 100644 --- a/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java +++ b/tests/src/test/java/net/devh/boot/grpc/test/inject/GrpcClientMetricsTest.java @@ -1,18 +1,17 @@ /* - * Copyright (c) 2016-2023 Michael Zhang + * Copyright (c) 2016-2023 The gRPC-Spring Authors * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the - * Software. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package net.devh.boot.grpc.test.inject; From 3f3bd29b267887b89ce6bda3400fcc36074c732f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=88=98=ED=98=84?= Date: Tue, 23 Apr 2024 14:25:42 +0900 Subject: [PATCH 6/6] Revert formatting changes. --- .../autoconfigure/GrpcClientAutoConfiguration.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/grpc-client-spring-boot-starter/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java b/grpc-client-spring-boot-starter/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java index 9cc48ae5e..9da74fe6a 100644 --- a/grpc-client-spring-boot-starter/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java +++ b/grpc-client-spring-boot-starter/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientAutoConfiguration.java @@ -152,7 +152,8 @@ List defaultChannelConfigurers() { "io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder"}) @Bean @Lazy - GrpcChannelFactory shadedNettyGrpcChannelFactory(final GrpcChannelsProperties properties, + GrpcChannelFactory shadedNettyGrpcChannelFactory( + final GrpcChannelsProperties properties, final GlobalClientInterceptorRegistry globalClientInterceptorRegistry, final List channelConfigurers) { @@ -169,7 +170,8 @@ GrpcChannelFactory shadedNettyGrpcChannelFactory(final GrpcChannelsProperties pr @ConditionalOnClass(name = {"io.netty.channel.Channel", "io.grpc.netty.NettyChannelBuilder"}) @Bean @Lazy - GrpcChannelFactory nettyGrpcChannelFactory(final GrpcChannelsProperties properties, + GrpcChannelFactory nettyGrpcChannelFactory( + final GrpcChannelsProperties properties, final GlobalClientInterceptorRegistry globalClientInterceptorRegistry, final List channelConfigurers) { @@ -185,7 +187,8 @@ GrpcChannelFactory nettyGrpcChannelFactory(final GrpcChannelsProperties properti @ConditionalOnMissingBean(GrpcChannelFactory.class) @Bean @Lazy - GrpcChannelFactory inProcessGrpcChannelFactory(final GrpcChannelsProperties properties, + GrpcChannelFactory inProcessGrpcChannelFactory( + final GrpcChannelsProperties properties, final GlobalClientInterceptorRegistry globalClientInterceptorRegistry, final List channelConfigurers) {