GH-364 Additional cleanup and small refactoring for Kotlin lambda support

This commit is contained in:
Oleg Zhurakousky
2019-09-10 13:48:32 +02:00
parent 2aed5abff8
commit d93febd4c4
3 changed files with 28 additions and 22 deletions

View File

@@ -50,6 +50,16 @@ import org.springframework.util.CollectionUtils;
*/
public class FunctionRegistration<T> 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.
* <br>
* NOTE: This is not intended as oublis API
*/
public static String REGISTRATION_NAME_SUFFIX = "_registration";
private final Set<String> names = new LinkedHashSet<>();
private final Map<String, String> properties = new LinkedHashMap<>();

View File

@@ -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
*/

View File

@@ -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();