DATACMNS-669 - Register QuerydslPredicateArgumentResolver as bean.

If no QuerydslBinderCustomizer is configured on @QuerydslPredicate specifically, we now also consider the domain types repository as candidate for binding customization.

The lookup algorithm for explicitly configured customizers has been refined to try to find a bean in the BeanFactory first, resorting to on-the-fly creation eventually.

QuerydslPredicateArgumentResolver is now registered as a lazily initialized bean and its usage is guarded by checking presence of Querydsl itself.

The according test needs to do some reflection in order to stay out of trouble when types are loaded by different class loaders required to hide certain types.

Original pull request: #132.
This commit is contained in:
Christoph Strobl
2015-07-16 11:40:01 +02:00
committed by Oliver Gierke
parent cccfa5e5c5
commit 64c8549db4
4 changed files with 235 additions and 10 deletions

View File

@@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.geo.format.DistanceFormatter;
import org.springframework.data.geo.format.PointFormatter;
@@ -68,6 +69,17 @@ public class SpringDataWebConfiguration extends WebMvcConfigurerAdapter {
return new SortHandlerMethodArgumentResolver();
}
/**
* Default QuerydslPredicateArgumentResolver.
*
* @return
*/
@Bean
@Lazy
public QuerydslPredicateArgumentResolver querydslPredicateArgumentResolver() {
return new QuerydslPredicateArgumentResolver(conversionService.getObject());
}
/*
* (non-Javadoc)
* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#addFormatters(org.springframework.format.FormatterRegistry)
@@ -100,7 +112,7 @@ public class SpringDataWebConfiguration extends WebMvcConfigurerAdapter {
argumentResolvers.add(pageableResolver());
if (QueryDslUtils.QUERY_DSL_PRESENT) {
argumentResolvers.add(new QuerydslPredicateArgumentResolver(conversionService.getObject()));
argumentResolvers.add(querydslPredicateArgumentResolver());
}
ProxyingHandlerMethodArgumentResolver resolver = new ProxyingHandlerMethodArgumentResolver(
@@ -110,4 +122,5 @@ public class SpringDataWebConfiguration extends WebMvcConfigurerAdapter {
argumentResolvers.add(resolver);
}
}

View File

@@ -20,6 +20,7 @@ import java.util.Map.Entry;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -27,6 +28,7 @@ import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.querydsl.SimpleEntityPathResolver;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.LinkedMultiValueMap;
@@ -53,6 +55,8 @@ public class QuerydslPredicateArgumentResolver implements HandlerMethodArgumentR
private AutowireCapableBeanFactory beanFactory;
private Repositories repositories;
/**
* Creates a new {@link QuerydslPredicateArgumentResolver} using the given {@link ConversionService}.
*
@@ -69,7 +73,9 @@ public class QuerydslPredicateArgumentResolver implements HandlerMethodArgumentR
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.beanFactory = applicationContext.getAutowireCapableBeanFactory();
this.repositories = new Repositories(applicationContext);
}
/*
@@ -127,17 +133,48 @@ public class QuerydslPredicateArgumentResolver implements HandlerMethodArgumentR
EntityPath<?> path = SimpleEntityPathResolver.INSTANCE.createPath(domainType);
QuerydslBinderCustomizer customizer = findCustomizerForDomainType(annotation, domainType);
QuerydslBindings bindings = new QuerydslBindings();
if (annotation == null || annotation.bindings().equals(QuerydslBinderCustomizer.class)) {
return bindings;
if (customizer != null) {
customizer.customize(bindings, path);
}
Class<? extends QuerydslBinderCustomizer> type = annotation.bindings();
QuerydslBinderCustomizer<EntityPath<?>> customizer = beanFactory != null ? beanFactory.createBean(type)
: BeanUtils.instantiateClass(type);
customizer.customize(bindings, path);
return bindings;
}
@SuppressWarnings("unchecked")
private QuerydslBinderCustomizer<EntityPath<?>> findCustomizerForDomainType(QuerydslPredicate annotation,
Class<?> domainType) {
if (annotation == null || (annotation != null && annotation.bindings().equals(QuerydslBinderCustomizer.class))) {
if (repositories != null && repositories.hasRepositoryFor(domainType)) {
Object repository = this.repositories.getRepositoryFor(domainType);
if (repository instanceof QuerydslBinderCustomizer) {
return (QuerydslBinderCustomizer<EntityPath<?>>) repository;
}
}
return null;
}
return createQuerydslBinderCustomizer(annotation.bindings());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private QuerydslBinderCustomizer<EntityPath<?>> createQuerydslBinderCustomizer(
Class<? extends QuerydslBinderCustomizer> type) {
if (beanFactory == null) {
return BeanUtils.instantiateClass(type);
}
try {
return beanFactory.getBean(type);
} catch (NoSuchBeanDefinitionException e) {
}
return beanFactory.createBean(type);
}
}