Add FunctionFactoryMetadata interface for type discovery
The compiled functions implement that interface which means you can inspect the signature of the method that created them and discover its generic types.
This commit is contained in:
@@ -23,13 +23,12 @@ import java.util.function.Consumer;
|
||||
*
|
||||
* @param <T> output type of target Consumer
|
||||
*/
|
||||
public interface ConsumerProxy<T> extends Consumer<T> {
|
||||
public interface ConsumerProxy<T> extends Consumer<T>, FunctionFactoryMetadata {
|
||||
|
||||
default boolean isFluxConsumer() {
|
||||
return FunctionUtils.isFluxConsumer(getTarget());
|
||||
return FunctionUtils.isFluxConsumer(getFactoryMethod());
|
||||
}
|
||||
|
||||
Consumer<T> getTarget();
|
||||
|
||||
String getInputType();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 org.springframework.cloud.function.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface FunctionFactoryMetadata {
|
||||
|
||||
Method getFactoryMethod();
|
||||
|
||||
}
|
||||
@@ -24,15 +24,12 @@ import java.util.function.Function;
|
||||
* @param <T> input type of target Function
|
||||
* @param <R> output type of target Function
|
||||
*/
|
||||
public interface FunctionProxy<T, R> extends Function<T, R> {
|
||||
public interface FunctionProxy<T, R> extends Function<T, R>, FunctionFactoryMetadata {
|
||||
|
||||
default boolean isFluxFunction() {
|
||||
return FunctionUtils.isFluxFunction(getTarget());
|
||||
return FunctionUtils.isFluxFunction(getFactoryMethod());
|
||||
}
|
||||
|
||||
Function<T, R> getTarget();
|
||||
|
||||
String getInputType();
|
||||
|
||||
String getOutputType();
|
||||
}
|
||||
|
||||
@@ -118,4 +118,51 @@ public abstract class FunctionUtils {
|
||||
}
|
||||
return typeNames.toArray(new String[typeNames.size()]);
|
||||
}
|
||||
|
||||
public static boolean isFluxSupplier(Method method) {
|
||||
String[] types = getParameterizedTypeNamesForMethod(method, Supplier.class);
|
||||
if (ObjectUtils.isEmpty(types)) {
|
||||
return false;
|
||||
}
|
||||
return (types[0].startsWith(FLUX_CLASS_NAME));
|
||||
}
|
||||
|
||||
public static boolean isFluxConsumer(Method method) {
|
||||
String[] types = getParameterizedTypeNamesForMethod(method, Consumer.class);
|
||||
if (ObjectUtils.isEmpty(types)) {
|
||||
return false;
|
||||
}
|
||||
return (types[0].startsWith(FLUX_CLASS_NAME));
|
||||
}
|
||||
|
||||
public static boolean isFluxFunction(Method method) {
|
||||
String[] types = getParameterizedTypeNamesForMethod(method, Function.class);
|
||||
if (ObjectUtils.isEmpty(types)) {
|
||||
return false;
|
||||
}
|
||||
if (ObjectUtils.isEmpty(types) || types.length != 2) {
|
||||
return false;
|
||||
}
|
||||
return (types[0].startsWith(FLUX_CLASS_NAME)
|
||||
&& types[1].startsWith(FLUX_CLASS_NAME));
|
||||
}
|
||||
|
||||
private static String[] getParameterizedTypeNamesForMethod(Method method,
|
||||
Class<?> interfaceClass) {
|
||||
Type genericInterface = method.getGenericReturnType();
|
||||
if ((genericInterface instanceof ParameterizedType) && interfaceClass
|
||||
.getTypeName().equals(((ParameterizedType) genericInterface)
|
||||
.getRawType().getTypeName())) {
|
||||
ParameterizedType type = (ParameterizedType) genericInterface;
|
||||
Type[] args = type.getActualTypeArguments();
|
||||
if (args != null) {
|
||||
String[] typeNames = new String[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
typeNames[i] = args[i].getTypeName();
|
||||
}
|
||||
return typeNames;
|
||||
}
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,11 @@ import java.util.function.Supplier;
|
||||
*
|
||||
* @param <T> output type of target Supplier
|
||||
*/
|
||||
public interface SupplierProxy<T> extends Supplier<T> {
|
||||
public interface SupplierProxy<T> extends Supplier<T>, FunctionFactoryMetadata {
|
||||
|
||||
default boolean isFluxSupplier() {
|
||||
return FunctionUtils.isFluxSupplier(getTarget());
|
||||
return FunctionUtils.isFluxSupplier(getFactoryMethod());
|
||||
}
|
||||
|
||||
Supplier<T> getTarget();
|
||||
|
||||
String getOutputType();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 org.springframework.cloud.function.gateway;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.function.support.FunctionUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class FunctionUtilsTests {
|
||||
|
||||
@Test
|
||||
public void isFluxConsumer() {
|
||||
Method method = ReflectionUtils.findMethod(FunctionUtilsTests.class, "fluxConsumer");
|
||||
assertThat(FunctionUtils.isFluxConsumer(method)).isTrue();
|
||||
assertThat(FunctionUtils.isFluxSupplier(method)).isFalse();
|
||||
assertThat(FunctionUtils.isFluxFunction(method)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isFluxSupplier() {
|
||||
Method method = ReflectionUtils.findMethod(FunctionUtilsTests.class, "fluxSupplier");
|
||||
assertThat(FunctionUtils.isFluxSupplier(method)).isTrue();
|
||||
assertThat(FunctionUtils.isFluxConsumer(method)).isFalse();
|
||||
assertThat(FunctionUtils.isFluxFunction(method)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isFluxFunction() {
|
||||
Method method = ReflectionUtils.findMethod(FunctionUtilsTests.class, "fluxFunction");
|
||||
assertThat(FunctionUtils.isFluxFunction(method)).isTrue();
|
||||
assertThat(FunctionUtils.isFluxSupplier(method)).isFalse();
|
||||
assertThat(FunctionUtils.isFluxConsumer(method)).isFalse();
|
||||
}
|
||||
|
||||
public Function<Flux<Foo>, Flux<Foo>> fluxFunction() {
|
||||
return foos -> foos.map(foo -> new Foo());
|
||||
}
|
||||
|
||||
public Supplier<Flux<Foo>> fluxSupplier() {
|
||||
return () -> Flux.just(new Foo());
|
||||
}
|
||||
|
||||
public Consumer<Flux<Foo>> fluxConsumer() {
|
||||
return flux -> flux.subscribe(System.out::println);
|
||||
}
|
||||
|
||||
class Foo {}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user