Inspect bean class if it is available

Avoids instantiating beans if not necessary, and allows user to
provide Function as a @SpringBootApplication (for instance), or
more generally as a source to the application context (as opposed
to being component scanned).
This commit is contained in:
Dave Syer
2018-03-21 11:09:57 +00:00
parent 0bd71e61e0
commit a1b624b28a
3 changed files with 52 additions and 8 deletions

View File

@@ -99,7 +99,7 @@ public class FunctionType {
public static boolean isWrapper(Type type) {
if (type instanceof ParameterizedType) {
type = ((ParameterizedType)type).getRawType();
type = ((ParameterizedType) type).getRawType();
}
return Publisher.class.equals(type) || Flux.class.equals(type)
|| Mono.class.equals(type) || Optional.class.equals(type);
@@ -222,13 +222,19 @@ public class FunctionType {
private Class<?> findType(ParamType paramType) {
int index = paramType.isOutput() ? 1 : 0;
Type type = this.type;
if (type instanceof Class) {
for (Type iface : ((Class<?>) type).getGenericInterfaces()) {
boolean found = false;
while (!found && type instanceof Class && type != Object.class) {
Class<?> clz = (Class<?>) type;
for (Type iface : clz.getGenericInterfaces()) {
if (iface.getTypeName().startsWith("java.util.function")) {
type = iface;
found = true;
break;
}
}
if (!found) {
type = clz.getSuperclass();
}
}
Type param = extractType(type, paramType, index);
if (param != null) {

View File

@@ -539,14 +539,22 @@ public class ContextFunctionCatalogAutoConfiguration {
param = new FunctionType(resolvable.getType());
}
else {
Object bean = this.registry.getBean(name);
if (bean instanceof FunctionFactoryMetadata) {
FunctionFactoryMetadata<?> factory = (FunctionFactoryMetadata<?>) bean;
Type type = factory.getFactoryMethod().getGenericReturnType();
Class<?> beanClass = definition.getBeanClass();
if (beanClass != null && !FunctionFactoryMetadata.class
.isAssignableFrom(beanClass)) {
Type type = beanClass;
param = new FunctionType(type);
}
else {
param = new FunctionType(bean.getClass());
Object bean = this.registry.getBean(name);
if (bean instanceof FunctionFactoryMetadata) {
FunctionFactoryMetadata<?> factory = (FunctionFactoryMetadata<?>) bean;
Type type = factory.getFactoryMethod().getGenericReturnType();
param = new FunctionType(type);
}
else {
param = new FunctionType(bean.getClass());
}
}
}
}

View File

@@ -123,6 +123,20 @@ public class ContextFunctionCatalogAutoConfigurationTests {
.isEqualTo(Foo.class);
}
@Test
public void configurationFunction() {
create(FunctionConfiguration.class);
assertThat(context.getBean("foos")).isInstanceOf(Function.class);
assertThat(catalog.<Function<?, ?>>lookup(Function.class, "foos"))
.isInstanceOf(Function.class);
assertThat(inspector.getInputType(catalog.lookup(Function.class, "foos")))
.isEqualTo(String.class);
assertThat(inspector.getOutputType(catalog.lookup(Function.class, "foos")))
.isEqualTo(Foo.class);
assertThat(inspector.getInputWrapper(catalog.lookup(Function.class, "foos")))
.isEqualTo(Flux.class);
}
@Test
public void dependencyInjection() {
create(DependencyInjectionConfiguration.class);
@@ -558,6 +572,22 @@ public class ContextFunctionCatalogAutoConfigurationTests {
}
}
@EnableAutoConfiguration
@Configuration("foos")
protected static class FunctionConfiguration
implements Function<Flux<String>, Flux<Foo>> {
@Override
public Flux<Foo> apply(Flux<String> flux) {
return flux.map(foo -> new Foo(value() + ": " + foo.toUpperCase()));
}
@Bean
public String value() {
return "Hello";
}
}
@EnableAutoConfiguration
@Configuration
@ComponentScan(basePackageClasses = FooConfiguration.class)