From d93febd4c4624bb32e772ea7f93bfd783bd39cec Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 10 Sep 2019 13:48:32 +0200 Subject: [PATCH] GH-364 Additional cleanup and small refactoring for Kotlin lambda support --- .../context/FunctionRegistration.java | 10 ++++++ .../BeanFactoryAwareFunctionRegistry.java | 31 +++++++------------ ...tlinLambdaToFunctionAutoConfiguration.java | 9 ++++-- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java index af865f080..ea3852775 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java @@ -50,6 +50,16 @@ import org.springframework.util.CollectionUtils; */ public class FunctionRegistration implements BeanNameAware { + /** + * Suffix used to add to the name of FunctionRegistration bean that + * corresponds to the an actual function bean. It is often used when + * the actual function bean may not be a java Function (e.g., Kotlin) + * and certain custom wrapping is required. + *
+ * NOTE: This is not intended as oublis API + */ + public static String REGISTRATION_NAME_SUFFIX = "_registration"; + private final Set names = new LinkedHashSet<>(); private final Map properties = new LinkedHashMap<>(); 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 3708c0c4d..089452ad4 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 @@ -177,24 +177,17 @@ public class BeanFactoryAwareFunctionRegistry function = this.registrationsByName.get(name); } - if (function != null && this.isKotlin(function.getClass())) { - function = this.applicationContext.getBean("_" + name, FunctionRegistration.class); + if (function != null && this.notFunction(function.getClass()) + && this.applicationContext.containsBean(name + FunctionRegistration.REGISTRATION_NAME_SUFFIX)) { // e.g., Kotlin lambdas + function = this.applicationContext.getBean(name + FunctionRegistration.REGISTRATION_NAME_SUFFIX, FunctionRegistration.class); } return function; } - private boolean isKotlin(Class functionClass) { - if (functionClass != null) { - if ("kotlin.jvm.internal.Lambda".equals(functionClass.getName())) { - return true; - } - else { - return this.isKotlin(functionClass.getSuperclass()); - } - } - else { - return false; - } + private boolean notFunction(Class functionClass) { + return !Function.class.isAssignableFrom(functionClass) + && !Supplier.class.isAssignableFrom(functionClass) + && !Consumer.class.isAssignableFrom(functionClass); } @@ -204,8 +197,8 @@ public class BeanFactoryAwareFunctionRegistry beanDefinitionExists = this.applicationContext.getBeanFactory().containsBeanDefinition(names[i]); } if (!beanDefinitionExists) { - logger.info("BeanDefinition for function name(s) `" + Arrays.asList(names) + - "` can not be located. FunctionType will be based on " + function.getClass()); + logger.info("BeanDefinition for function name(s) '" + Arrays.asList(names) + + "' can not be located. FunctionType will be based on " + function.getClass()); } return beanDefinitionExists ? FunctionType.of(FunctionContextUtils.findType(applicationContext.getBeanFactory(), names)).getType() @@ -216,11 +209,11 @@ public class BeanFactoryAwareFunctionRegistry if (StringUtils.isEmpty(definition)) { // the underscores are for Kotlin function registrations (see KotlinLambdaToFunctionAutoConfiguration) String[] functionNames = Stream.of(this.applicationContext.getBeanNamesForType(Function.class)) - .filter(n -> !n.startsWith("_") && !n.equals(RoutingFunction.FUNCTION_NAME)).toArray(String[]::new); + .filter(n -> !n.endsWith(FunctionRegistration.REGISTRATION_NAME_SUFFIX) && !n.equals(RoutingFunction.FUNCTION_NAME)).toArray(String[]::new); String[] consumerNames = Stream.of(this.applicationContext.getBeanNamesForType(Consumer.class)) - .filter(n -> !n.startsWith("_") && !n.equals(RoutingFunction.FUNCTION_NAME)).toArray(String[]::new); + .filter(n -> !n.endsWith(FunctionRegistration.REGISTRATION_NAME_SUFFIX) && !n.equals(RoutingFunction.FUNCTION_NAME)).toArray(String[]::new); String[] supplierNames = Stream.of(this.applicationContext.getBeanNamesForType(Supplier.class)) - .filter(n -> !n.startsWith("_") && !n.equals(RoutingFunction.FUNCTION_NAME)).toArray(String[]::new); + .filter(n -> !n.endsWith(FunctionRegistration.REGISTRATION_NAME_SUFFIX) && !n.equals(RoutingFunction.FUNCTION_NAME)).toArray(String[]::new); /* * we may need to add BiFunction and BiConsumer at some point */ diff --git a/spring-cloud-function-kotlin/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java b/spring-cloud-function-kotlin/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java index bf9e43350..e862ae924 100644 --- a/spring-cloud-function-kotlin/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java +++ b/spring-cloud-function-kotlin/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java @@ -57,7 +57,7 @@ import org.springframework.util.ObjectUtils; * @since 2.0 */ @Configuration -@ConditionalOnClass(name = "kotlin.jvm.functions.Function1") +@ConditionalOnClass(name = "kotlin.jvm.functions.Function0") class KotlinLambdaToFunctionAutoConfiguration { protected final Log logger = LogFactory.getLog(getClass()); @@ -88,7 +88,7 @@ class KotlinLambdaToFunctionAutoConfiguration { ConstructorArgumentValues ca = new ConstructorArgumentValues(); ca.addGenericArgumentValue(beanDefinition); cbd.setConstructorArgumentValues(ca); - ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition("_" + beanDefinitionName, cbd); + ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(beanDefinitionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX, cbd); } } } @@ -164,7 +164,10 @@ class KotlinLambdaToFunctionAutoConfiguration { @Override public FunctionRegistration getObject() throws Exception { - Type functionType = FunctionContextUtils.findType(this.name.substring(1), this.beanFactory); + String name = this.name.endsWith(FunctionRegistration.REGISTRATION_NAME_SUFFIX) + ? this.name.replace(FunctionRegistration.REGISTRATION_NAME_SUFFIX, "") + : this.name; + Type functionType = FunctionContextUtils.findType(name, this.beanFactory); FunctionRegistration registration = new FunctionRegistration<>(this, name); Type[] types = ((ParameterizedType) functionType).getActualTypeArguments();