Add flag for disabling component scan

This commit is contained in:
Dave Syer
2019-07-10 17:08:41 +01:00
committed by Oleg Zhurakousky
parent 307292b959
commit b4f5c0339f
3 changed files with 86 additions and 105 deletions

View File

@@ -78,11 +78,8 @@ import org.springframework.messaging.converter.StringMessageConverter;
* @author Artem Bilan
* @author Anshul Mehra
*/
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(FunctionCatalog.class)
@ComponentScan(basePackages = "${spring.cloud.function.scan.packages:functions}", //
includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
Supplier.class, Function.class, Consumer.class }))
public class ContextFunctionCatalogAutoConfiguration {
static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
@@ -103,9 +100,18 @@ public class ContextFunctionCatalogAutoConfiguration {
return new RoutingFunction(functionCatalog, functionInspector, messageConverter);
}
protected static class BeanFactoryFunctionCatalog
extends AbstractComposableFunctionRegistry
implements SmartInitializingSingleton, BeanFactoryAware {
@Configuration(proxyBeanMethods = false)
@ComponentScan(basePackages = "${spring.cloud.function.scan.packages:functions}", //
includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE,
classes = { Supplier.class, Function.class, Consumer.class }))
@ConditionalOnProperty(prefix = "spring.cloud.function.scan", name = "enabled", havingValue = "true",
matchIfMissing = true)
protected static class PlainFunctionScanConfiguration {
}
protected static class BeanFactoryFunctionCatalog extends AbstractComposableFunctionRegistry
implements SmartInitializingSingleton, BeanFactoryAware {
private ApplicationEventPublisher applicationEventPublisher;
@@ -118,16 +124,12 @@ public class ContextFunctionCatalogAutoConfiguration {
@SuppressWarnings("rawtypes")
@Override
public void afterSingletonsInstantiated() {
Map<String, Supplier> supplierBeans = this.beanFactory
.getBeansOfType(Supplier.class);
Map<String, Function> functionBeans = this.beanFactory
.getBeansOfType(Function.class);
Map<String, Consumer> consumerBeans = this.beanFactory
.getBeansOfType(Consumer.class);
Map<String, Supplier> supplierBeans = this.beanFactory.getBeansOfType(Supplier.class);
Map<String, Function> functionBeans = this.beanFactory.getBeansOfType(Function.class);
Map<String, Consumer> consumerBeans = this.beanFactory.getBeansOfType(Consumer.class);
Map<String, FunctionRegistration> functionRegistrationBeans = this.beanFactory
.getBeansOfType(FunctionRegistration.class);
this.doMerge(functionRegistrationBeans, consumerBeans, supplierBeans,
functionBeans);
.getBeansOfType(FunctionRegistration.class);
this.doMerge(functionRegistrationBeans, consumerBeans, supplierBeans, functionBeans);
}
@Override
@@ -139,14 +141,12 @@ public class ContextFunctionCatalogAutoConfiguration {
public void close() {
if (this.applicationEventPublisher != null) {
if (this.hasFunctions()) {
this.applicationEventPublisher
.publishEvent(new FunctionUnregistrationEvent(this,
Function.class, this.getFunctionNames()));
this.applicationEventPublisher.publishEvent(
new FunctionUnregistrationEvent(this, Function.class, this.getFunctionNames()));
}
if (this.hasSuppliers()) {
this.applicationEventPublisher
.publishEvent(new FunctionUnregistrationEvent(this,
Supplier.class, this.getSupplierNames()));
this.applicationEventPublisher.publishEvent(
new FunctionUnregistrationEvent(this, Supplier.class, this.getSupplierNames()));
}
}
}
@@ -155,8 +155,7 @@ public class ContextFunctionCatalogAutoConfiguration {
protected FunctionType findType(FunctionRegistration<?> functionRegistration, String name) {
FunctionType functionType = super.findType(functionRegistration, name);
if (functionType == null) {
functionType = functionByNameExist(name)
? new FunctionType(functionRegistration.getTarget().getClass())
functionType = functionByNameExist(name) ? new FunctionType(functionRegistration.getTarget().getClass())
: this.findType(name);
}
@@ -179,9 +178,8 @@ public class ContextFunctionCatalogAutoConfiguration {
*/
@Deprecated
@SuppressWarnings("rawtypes")
Set<FunctionRegistration<?>> merge(Map<String, FunctionRegistration> initial,
Map<String, Consumer> consumers, Map<String, Supplier> suppliers,
Map<String, Function> functions) {
Set<FunctionRegistration<?>> merge(Map<String, FunctionRegistration> initial, Map<String, Consumer> consumers,
Map<String, Supplier> suppliers, Map<String, Function> functions) {
this.doMerge(initial, consumers, suppliers, functions);
return null;
}
@@ -198,14 +196,13 @@ public class ContextFunctionCatalogAutoConfiguration {
}
private String getQualifier(String key) {
if (this.beanFactory != null
&& this.beanFactory.containsBeanDefinition(key)) {
if (this.beanFactory != null && this.beanFactory.containsBeanDefinition(key)) {
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition(key);
Object source = beanDefinition.getSource();
if (source instanceof StandardMethodMetadata) {
StandardMethodMetadata metadata = (StandardMethodMetadata) source;
Qualifier qualifier = AnnotatedElementUtils.findMergedAnnotation(
metadata.getIntrospectedMethod(), Qualifier.class);
Qualifier qualifier = AnnotatedElementUtils.findMergedAnnotation(metadata.getIntrospectedMethod(),
Qualifier.class);
if (qualifier != null && qualifier.value().length() > 0) {
return qualifier.value();
}
@@ -215,8 +212,7 @@ public class ContextFunctionCatalogAutoConfiguration {
}
private boolean functionByNameExist(String name) {
return name == null || this.beanFactory == null
|| !this.beanFactory.containsBeanDefinition(name);
return name == null || this.beanFactory == null || !this.beanFactory.containsBeanDefinition(name);
}
@SuppressWarnings("rawtypes")
@@ -236,21 +232,20 @@ public class ContextFunctionCatalogAutoConfiguration {
targets.put(registration.getTarget(), key);
}
Stream.concat(consumerBeans.entrySet().stream(), Stream.concat(
supplierBeans.entrySet().stream(), functionBeans.entrySet().stream()))
Stream.concat(consumerBeans.entrySet().stream(),
Stream.concat(supplierBeans.entrySet().stream(), functionBeans.entrySet().stream()))
.forEach(entry -> {
if (!targets.containsKey(entry.getValue())) {
FunctionRegistration<Object> target = new FunctionRegistration<Object>(
entry.getValue(),
FunctionRegistration<Object> target = new FunctionRegistration<Object>(entry.getValue(),
getAliases(entry.getKey()).toArray(new String[] {}));
targets.put(target.getTarget(), entry.getKey());
registrations.add(target);
}
});
registrations.forEach(registration -> register(registration,
targets.get(registration.getTarget())));
registrations.forEach(registration -> register(registration, targets.get(registration.getTarget())));
}
}
private static class PreferGsonOrMissingJacksonCondition extends AnyNestedCondition {
@@ -271,7 +266,7 @@ public class ContextFunctionCatalogAutoConfiguration {
}
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Gson.class)
@ConditionalOnBean(Gson.class)
@Conditional(PreferGsonOrMissingJacksonCondition.class)
@@ -284,7 +279,7 @@ public class ContextFunctionCatalogAutoConfiguration {
}
@Configuration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ObjectMapper.class)
@ConditionalOnBean(ObjectMapper.class)
@ConditionalOnProperty(name = ContextFunctionCatalogAutoConfiguration.PREFERRED_MAPPER_PROPERTY, //

View File

@@ -55,8 +55,7 @@ import org.springframework.util.ClassUtils;
* @author Dave Syer
*
*/
public class ContextFunctionCatalogInitializer
implements ApplicationContextInitializer<GenericApplicationContext> {
public class ContextFunctionCatalogInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
/**
* Property name for ignoring pre initilizer.
@@ -70,32 +69,27 @@ public class ContextFunctionCatalogInitializer
@Override
public void initialize(GenericApplicationContext applicationContext) {
if (enabled && applicationContext.getEnvironment()
.getProperty("spring.functional.enabled", Boolean.class, false)) {
ContextFunctionCatalogBeanRegistrar registrar = new ContextFunctionCatalogBeanRegistrar(
applicationContext);
if (enabled
&& applicationContext.getEnvironment().getProperty("spring.functional.enabled", Boolean.class, false)) {
ContextFunctionCatalogBeanRegistrar registrar = new ContextFunctionCatalogBeanRegistrar(applicationContext);
applicationContext.addBeanFactoryPostProcessor(registrar);
}
}
static class ContextFunctionCatalogBeanRegistrar
implements BeanDefinitionRegistryPostProcessor {
static class ContextFunctionCatalogBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
private GenericApplicationContext context;
ContextFunctionCatalogBeanRegistrar(
GenericApplicationContext applicationContext) {
ContextFunctionCatalogBeanRegistrar(GenericApplicationContext applicationContext) {
this.context = applicationContext;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
try {
register(registry, this.context.getDefaultListableBeanFactory());
}
@@ -110,52 +104,41 @@ public class ContextFunctionCatalogInitializer
}
}
protected void register(BeanDefinitionRegistry registry,
ConfigurableListableBeanFactory factory) throws Exception {
protected void register(BeanDefinitionRegistry registry, ConfigurableListableBeanFactory factory)
throws Exception {
performPreinitialization();
if (this.context.getBeanFactory().getBeanNamesForType(
PropertySourcesPlaceholderConfigurer.class, false,
if (this.context.getBeanFactory().getBeanNamesForType(PropertySourcesPlaceholderConfigurer.class, false,
false).length == 0) {
this.context.registerBean(PropertySourcesPlaceholderConfigurer.class,
() -> PropertyPlaceholderAutoConfiguration
.propertySourcesPlaceholderConfigurer());
() -> PropertyPlaceholderAutoConfiguration.propertySourcesPlaceholderConfigurer());
}
if (!this.context.getBeanFactory().containsBean(
AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
if (!this.context.getBeanFactory()
.containsBean(AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// Switch off the ConfigurationClassPostProcessor
this.context.registerBean(
AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME,
this.context.registerBean(AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME,
DummyProcessor.class, () -> new DummyProcessor());
// But switch on other annotation processing
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.context);
}
if (!this.context.getBeanFactory().containsBean(
ConfigurationPropertiesBindingPostProcessor.BEAN_NAME)) {
new ConfigurationPropertiesBindingPostProcessorRegistrar()
.registerBeanDefinitions(null, context);
if (!this.context.getBeanFactory().containsBean(ConfigurationPropertiesBindingPostProcessor.BEAN_NAME)) {
new ConfigurationPropertiesBindingPostProcessorRegistrar().registerBeanDefinitions(null, this.context);
}
if (ClassUtils.isPresent("com.google.gson.Gson", null)
&& "gson".equals(this.context.getEnvironment().getProperty(
ContextFunctionCatalogAutoConfiguration.PREFERRED_MAPPER_PROPERTY,
"gson"))) {
if (this.context.getBeanFactory().getBeanNamesForType(Gson.class, false,
false).length == 0) {
if (ClassUtils.isPresent("com.google.gson.Gson", null) && "gson".equals(this.context.getEnvironment()
.getProperty(ContextFunctionCatalogAutoConfiguration.PREFERRED_MAPPER_PROPERTY, "gson"))) {
if (this.context.getBeanFactory().getBeanNamesForType(Gson.class, false, false).length == 0) {
this.context.registerBean(Gson.class, () -> new Gson());
}
this.context.registerBean(JsonMapper.class,
() -> new ContextFunctionCatalogAutoConfiguration.GsonConfiguration()
.jsonMapper(this.context.getBean(Gson.class)));
}
else if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
null)) {
if (this.context.getBeanFactory().getBeanNamesForType(ObjectMapper.class,
false, false).length == 0) {
this.context.registerBean(ObjectMapper.class,
() -> new ObjectMapper());
else if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
if (this.context.getBeanFactory().getBeanNamesForType(ObjectMapper.class, false, false).length == 0) {
this.context.registerBean(ObjectMapper.class, () -> new ObjectMapper());
}
this.context.registerBean(JsonMapper.class,
() -> new ContextFunctionCatalogAutoConfiguration.JacksonConfiguration()
@@ -163,35 +146,29 @@ public class ContextFunctionCatalogInitializer
}
String basePackage = this.context.getEnvironment()
.getProperty("spring.cloud.function.scan.packages", "functions");
if (new ClassPathResource(basePackage.replace(".", "/")).exists()) {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(
this.context, false, this.context.getEnvironment(), this.context);
String basePackage = this.context.getEnvironment().getProperty("spring.cloud.function.scan.packages",
"functions");
if (this.context.getEnvironment().getProperty("spring.cloud.function.scan.enabled", Boolean.class, true)
&& new ClassPathResource(basePackage.replace(".", "/")).exists()) {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.context, false,
this.context.getEnvironment(), this.context);
scanner.addIncludeFilter(new AssignableTypeFilter(Function.class));
scanner.addIncludeFilter(new AssignableTypeFilter(Supplier.class));
scanner.addIncludeFilter(new AssignableTypeFilter(Consumer.class));
for (BeanDefinition bean : scanner.findCandidateComponents(basePackage)) {
String name = bean.getBeanClassName();
Class<?> type = ClassUtils.resolveClassName(name,
this.context.getClassLoader());
Class<?> type = ClassUtils.resolveClassName(name, this.context.getClassLoader());
this.context.registerBeanDefinition(name, bean);
this.context.registerBean("registration_" + name,
FunctionRegistration.class,
() -> new FunctionRegistration<>(this.context.getBean(name),
name).type(type));
this.context.registerBean("registration_" + name, FunctionRegistration.class,
() -> new FunctionRegistration<>(this.context.getBean(name), name).type(type));
}
}
if (this.context.getBeanFactory().getBeanNamesForType(FunctionCatalog.class,
false, false).length == 0) {
this.context.registerBean(InMemoryFunctionCatalog.class,
() -> new InMemoryFunctionCatalog());
this.context
.registerBean(FunctionRegistrationPostProcessor.class,
() -> new FunctionRegistrationPostProcessor(this.context
.getAutowireCapableBeanFactory()
.getBeanProvider(FunctionRegistration.class)));
if (this.context.getBeanFactory().getBeanNamesForType(FunctionCatalog.class, false, false).length == 0) {
this.context.registerBean(InMemoryFunctionCatalog.class, () -> new InMemoryFunctionCatalog());
this.context.registerBean(FunctionRegistrationPostProcessor.class,
() -> new FunctionRegistrationPostProcessor(this.context.getAutowireCapableBeanFactory()
.getBeanProvider(FunctionRegistration.class)));
}
}
@@ -234,8 +211,7 @@ public class ContextFunctionCatalogInitializer
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof FunctionRegistry) {
FunctionRegistry catalog = (FunctionRegistry) bean;
for (FunctionRegistration<?> registration : this.functions) {
@@ -243,8 +219,7 @@ public class ContextFunctionCatalogInitializer
"FunctionRegistration must define at least one name. Was empty");
if (registration.getType() == null) {
throw new IllegalStateException(
"You need an explicit type for the function: "
+ registration.getNames());
"You need an explicit type for the function: " + registration.getNames());
// TODO: in principle Spring could know how to extract this
// from the supplier, but in practice there is no functional
// bean registration with parametric types.