From b61e3571440b4ec6435ffb759a4cbcbfe5547397 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 22 Oct 2020 09:58:34 +0200 Subject: [PATCH] Add function type discovery method to FunctionTypeUtils --- .../BeanFactoryAwareFunctionRegistry.java | 54 ++--------- .../context/catalog/FunctionTypeUtils.java | 96 +++++++++++++------ 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java index 8c1d41282..c1101d347 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java @@ -29,13 +29,11 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.BeansException; -import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils; import org.springframework.cloud.function.context.FunctionProperties; import org.springframework.cloud.function.context.FunctionRegistration; -import org.springframework.cloud.function.context.FunctionType; -import org.springframework.cloud.function.context.config.FunctionContextUtils; -import org.springframework.cloud.function.context.config.RoutingFunction; +import org.springframework.cloud.function.context.FunctionRegistry; import org.springframework.cloud.function.json.JsonMapper; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -44,6 +42,11 @@ import org.springframework.core.convert.ConversionService; import org.springframework.messaging.converter.CompositeMessageConverter; import org.springframework.util.StringUtils; +/** + * Implementation of {@link FunctionRegistry} capable of discovering functioins in {@link BeanFactory} + * + * @author Oleg Zhurakousky + */ public class BeanFactoryAwareFunctionRegistry extends SimpleFunctionRegistry implements ApplicationContextAware { private GenericApplicationContext applicationContext; @@ -129,7 +132,7 @@ public class BeanFactoryAwareFunctionRegistry extends SimpleFunctionRegistry imp .getBean(functionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX, FunctionRegistration.class); } else { - functionType = this.discoverFunctionType(functionCandidate, functionName); + functionType = FunctionTypeUtils.discoverFunctionType(functionCandidate, functionName, this.applicationContext); } if (functionRegistration == null) { functionRegistration = new FunctionRegistration(functionCandidate, functionName).type(functionType); @@ -171,47 +174,6 @@ public class BeanFactoryAwareFunctionRegistry extends SimpleFunctionRegistry imp return super.containsFunction(functionName) ? true : this.applicationContext.containsBean(functionName); } - @SuppressWarnings("rawtypes") - Type discoverFunctionType(Object function, String functionName) { - if (function instanceof RoutingFunction) { - return FunctionType.of(FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionName)).getType(); - } - else if (function instanceof FunctionRegistration) { - return ((FunctionRegistration) function).getType().getType(); - } - boolean beanDefinitionExists = false; - String functionBeanDefinitionName = this.discoverDefinitionName(functionName); - beanDefinitionExists = this.applicationContext.getBeanFactory().containsBeanDefinition(functionBeanDefinitionName); - if (this.applicationContext.containsBean("&" + functionName)) { - Class objectType = this.applicationContext.getBean("&" + functionName, FactoryBean.class) - .getObjectType(); - return FunctionTypeUtils.discoverFunctionTypeFromClass(objectType); - } -// if (!beanDefinitionExists) { -// logger.info("BeanDefinition for function name(s) '" + Arrays.asList(names) + -// "' can not be located. FunctionType will be based on " + function.getClass()); -// } - - Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(function.getClass()); - if (beanDefinitionExists) { - Type t = FunctionTypeUtils.getImmediateGenericType(type, 0); - if (t == null || t == Object.class) { - type = FunctionType.of(FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), functionBeanDefinitionName)).getType(); - } - } - return type; - } - - private String discoverDefinitionName(String functionDefinition) { - String[] aliases = this.applicationContext.getAliases(functionDefinition); - for (String alias : aliases) { - if (this.applicationContext.getBeanFactory().containsBeanDefinition(alias)) { - return alias; - } - } - return functionDefinition; - } - private boolean isFunctionPojo(Object functionCandidate, String functionName) { return !functionCandidate.getClass().isSynthetic() && !(functionCandidate instanceof Supplier) diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java index 30e079e4f..bed482773 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java @@ -36,7 +36,12 @@ import org.apache.commons.logging.LogFactory; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import org.springframework.beans.factory.FactoryBean; import org.springframework.cloud.function.context.FunctionRegistration; +import org.springframework.cloud.function.context.FunctionType; +import org.springframework.cloud.function.context.config.FunctionContextUtils; +import org.springframework.cloud.function.context.config.RoutingFunction; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.ResolvableType; import org.springframework.messaging.Message; import org.springframework.util.Assert; @@ -223,6 +228,33 @@ public final class FunctionTypeUtils { return inputType; } + @SuppressWarnings("rawtypes") + public static Type discoverFunctionType(Object function, String functionName, GenericApplicationContext applicationContext) { + if (function instanceof RoutingFunction) { + return FunctionType.of(FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionName)).getType(); + } + else if (function instanceof FunctionRegistration) { + return ((FunctionRegistration) function).getType().getType(); + } + boolean beanDefinitionExists = false; + String functionBeanDefinitionName = discoverDefinitionName(functionName, applicationContext); + beanDefinitionExists = applicationContext.getBeanFactory().containsBeanDefinition(functionBeanDefinitionName); + if (applicationContext.containsBean("&" + functionName)) { + Class objectType = applicationContext.getBean("&" + functionName, FactoryBean.class) + .getObjectType(); + return FunctionTypeUtils.discoverFunctionTypeFromClass(objectType); + } + + Type type = FunctionTypeUtils.discoverFunctionTypeFromClass(function.getClass()); + if (beanDefinitionExists) { + Type t = FunctionTypeUtils.getImmediateGenericType(type, 0); + if (t == null || t == Object.class) { + type = FunctionType.of(FunctionContextUtils.findType(applicationContext.getBeanFactory(), functionBeanDefinitionName)).getType(); + } + } + return type; + } + @SuppressWarnings("unchecked") public static Type getOutputType(Type functionType) { assertSupportedTypes(functionType); @@ -291,34 +323,11 @@ public final class FunctionTypeUtils { return isOfType(type, Consumer.class); } - private static boolean isOfType(Type type, Class cls) { - if (type instanceof Class) { - return cls.isAssignableFrom((Class) type); - } - else if (type instanceof ParameterizedType) { - return isOfType(((ParameterizedType) type).getRawType(), cls); - } - return false; - } - public static boolean isMono(Type type) { type = extractReactiveType(type); return type == null ? false : type.getTypeName().startsWith("reactor.core.publisher.Mono"); } - private static boolean isFunctional(Type type) { - if (type instanceof ParameterizedType) { - type = ((ParameterizedType) type).getRawType(); - Assert.isTrue(type instanceof Class, "Must be one of Supplier, Function, Consumer" - + " or FunctionRegistration. Was " + type); - } - - Class candidateType = (Class) type; - return Supplier.class.isAssignableFrom(candidateType) - || Function.class.isAssignableFrom(candidateType) - || Consumer.class.isAssignableFrom(candidateType); - } - public static boolean isMultipleArgumentType(Type type) { if (type != null) { if (TypeResolver.resolveRawClass(type, null).isArray()) { @@ -350,12 +359,6 @@ public final class FunctionTypeUtils { ResolvableType.forMethodReturnType(functionalMethod)).getType(); } break; -// case 2: -// ResolvableType canonicalParametersWrapper = fromTwoArityFunction(functionalMethod); -// functionType = ResolvableType.forClassWithGenerics(Function.class, -// canonicalParametersWrapper, -// ResolvableType.forMethodReturnType(functionalMethod)).getType(); -// break; default: throw new UnsupportedOperationException("Functional method: " + functionalMethod + " is not supported"); } @@ -366,6 +369,16 @@ public final class FunctionTypeUtils { return type.getTypeName().startsWith("reactor.util.function.Tuple"); } + private static boolean isOfType(Type type, Class cls) { + if (type instanceof Class) { + return cls.isAssignableFrom((Class) type); + } + else if (type instanceof ParameterizedType) { + return isOfType(((ParameterizedType) type).getRawType(), cls); + } + return false; + } + private static void assertSupportedTypes(Type type) { if (type instanceof ParameterizedType) { type = ((ParameterizedType) type).getRawType(); @@ -392,4 +405,29 @@ public final class FunctionTypeUtils { } return type; } + + private static String discoverDefinitionName(String functionDefinition, GenericApplicationContext applicationContext) { + String[] aliases = applicationContext.getAliases(functionDefinition); + for (String alias : aliases) { + if (applicationContext.getBeanFactory().containsBeanDefinition(alias)) { + return alias; + } + } + return functionDefinition; + } + + private static boolean isFunctional(Type type) { + if (type instanceof ParameterizedType) { + type = ((ParameterizedType) type).getRawType(); + Assert.isTrue(type instanceof Class, "Must be one of Supplier, Function, Consumer" + + " or FunctionRegistration. Was " + type); + } + + Class candidateType = (Class) type; + return Supplier.class.isAssignableFrom(candidateType) + || Function.class.isAssignableFrom(candidateType) + || Consumer.class.isAssignableFrom(candidateType) + || BiFunction.class.isAssignableFrom(candidateType) + || BiConsumer.class.isAssignableFrom(candidateType); + } }