Add other annotation processors to functional context

This commit is contained in:
Dave Syer
2018-10-18 09:36:13 +01:00
parent ae07a13d03
commit c4ee7ab065
3 changed files with 116 additions and 8 deletions

View File

@@ -22,7 +22,6 @@ import com.google.gson.Gson;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -39,6 +38,7 @@ import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -108,10 +108,13 @@ public class ContextFunctionCatalogInitializer
}
if (!context.getBeanFactory().containsBean(
AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// Switch off the ConfigurationClassPostProcessor
context.registerBean(
AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME,
AutowiredAnnotationBeanPostProcessor.class);
AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME,
DummyProcessor.class, () -> new DummyProcessor());
// But switch on other annotation processing
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
}
if (!context.getBeanFactory()
.containsBean(ConfigurationBeanFactoryMetadata.BEAN_NAME)) {
@@ -220,5 +223,9 @@ public class ContextFunctionCatalogInitializer
}
}
public static class DummyProcessor {
public void setMetadataReaderFactory(MetadataReaderFactory obj) {}
}
}

View File

@@ -16,25 +16,24 @@
package org.springframework.cloud.function.context.config;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.junit.Test;
import org.reactivestreams.Publisher;
import org.springframework.cloud.function.context.FunctionRegistration;
import org.springframework.cloud.function.context.FunctionType;
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration.BeanFactoryFunctionCatalog;
import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration.ContextFunctionRegistry;
import static org.assertj.core.api.Assertions.assertThat;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

View File

@@ -18,7 +18,9 @@ package org.springframework.cloud.function.context.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -26,10 +28,13 @@ import java.util.function.Supplier;
import com.google.gson.Gson;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.function.context.FunctionCatalog;
import org.springframework.cloud.function.context.FunctionRegistration;
import org.springframework.cloud.function.context.FunctionType;
@@ -37,6 +42,8 @@ import org.springframework.cloud.function.context.catalog.FunctionInspector;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.MapPropertySource;
import org.springframework.util.StringUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -66,6 +73,40 @@ public class ContextFunctionCatalogInitializerTests {
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
assertThat((Function<?, ?>) catalog.lookup(Function.class, "function"))
.isInstanceOf(Function.class);
}
@Test
public void properties() {
create(PropertiesConfiguration.class, "app.greeting=hello");
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
@SuppressWarnings("unchecked")
Function<Flux<String>, Flux<String>> function = (Function<Flux<String>, Flux<String>>) catalog
.lookup(Function.class, "function");
assertThat(function).isInstanceOf(Function.class);
assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("hello foo");
}
@Test
public void value() {
create(ValueConfiguration.class, "app.greeting=hello");
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
@SuppressWarnings("unchecked")
Function<Flux<String>, Flux<String>> function = (Function<Flux<String>, Flux<String>>) catalog
.lookup(Function.class, "function");
assertThat(function).isInstanceOf(Function.class);
assertThat(function.apply(Flux.just("foo")).blockFirst()).isEqualTo("hello foo");
}
@Test
@Ignore
public void compose() {
create(SimpleConfiguration.class);
assertThat(context.getBean("function")).isInstanceOf(FunctionRegistration.class);
@SuppressWarnings("unchecked")
Supplier<Flux<String>> supplier = (Supplier<Flux<String>>) catalog
.lookup(Supplier.class, "supplier|function");
assertThat(supplier).isInstanceOf(Supplier.class);
assertThat(supplier.get().blockFirst()).isEqualTo("HELLO");
// TODO: support for function composition
}
@@ -153,6 +194,17 @@ public class ContextFunctionCatalogInitializerTests {
private void create(ApplicationContextInitializer<GenericApplicationContext>[] types,
String... props) {
context = new GenericApplicationContext();
Map<String, Object> map = new HashMap<>();
for (String prop : props) {
String[] array = StringUtils.delimitedListToStringArray(prop, "=");
String key = array[0];
String value = array.length > 1 ? array[1] : "";
map.put(key, value);
}
if (!map.isEmpty()) {
context.getEnvironment().getPropertySources()
.addFirst(new MapPropertySource("testProperties", map));
}
for (ApplicationContextInitializer<GenericApplicationContext> type : types) {
type.initialize(context);
}
@@ -222,6 +274,56 @@ public class ContextFunctionCatalogInitializerTests {
}
}
@ConfigurationProperties("app")
protected static class PropertiesConfiguration
implements ApplicationContextInitializer<GenericApplicationContext> {
private String greeting;
public String getGreeting() {
return this.greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
@Override
public void initialize(GenericApplicationContext context) {
context.registerBean("function", FunctionRegistration.class,
() -> new FunctionRegistration<>(function()).type(
FunctionType.from(String.class).to(String.class).getType()));
context.registerBean(PropertiesConfiguration.class, () -> this);
}
@Bean
public Function<String, String> function() {
return value -> greeting + " " + value;
}
}
protected static class ValueConfiguration
implements ApplicationContextInitializer<GenericApplicationContext> {
@Value("${app.greeting}")
private String greeting;
@Override
public void initialize(GenericApplicationContext context) {
context.registerBean("function", FunctionRegistration.class,
() -> new FunctionRegistration<>(function()).type(
FunctionType.from(String.class).to(String.class).getType()));
context.registerBean(ValueConfiguration.class, () -> this);
}
@Bean
public Function<String, String> function() {
return value -> greeting + " " + value;
}
}
protected static class GsonConfiguration
implements ApplicationContextInitializer<GenericApplicationContext> {