mirror of
https://github.com/spring-projects/spring-data-commons.git
synced 2026-05-03 03:34:35 +01:00
DATACMNS-1158 - ProjectionFactory is now configurable by module implementations.
Introduced RepositoryFactorySupport.getProjectionFactory(…) to create a ProjectionFactory to be used for repository instances created. The default implementation uses the SpelAwareProxyProjectionFactory. The ProjectionInformation implementation is now a named class so it can be used for more specialized implementations. Original pull request: #243. Related issue: DATAJPA-1173.
This commit is contained in:
+26
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
* Copyright 2015-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.
|
||||
@@ -77,7 +77,8 @@ public class SpelAwareProxyProjectionFactory extends ProxyProjectionFactory impl
|
||||
}
|
||||
|
||||
return typeCache.get(projectionType)
|
||||
? new SpelEvaluatingMethodInterceptor(interceptor, source, beanFactory, parser, projectionType) : interceptor;
|
||||
? new SpelEvaluatingMethodInterceptor(interceptor, source, beanFactory, parser, projectionType)
|
||||
: interceptor;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -86,28 +87,33 @@ public class SpelAwareProxyProjectionFactory extends ProxyProjectionFactory impl
|
||||
*/
|
||||
@Override
|
||||
public ProjectionInformation getProjectionInformation(Class<?> projectionType) {
|
||||
return new SpelAwareProjectionInformation(projectionType);
|
||||
}
|
||||
|
||||
return new DefaultProjectionInformation(projectionType) {
|
||||
protected static class SpelAwareProjectionInformation extends DefaultProjectionInformation {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.projection.DefaultProjectionInformation#isInputProperty(java.beans.PropertyDescriptor)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isInputProperty(PropertyDescriptor descriptor) {
|
||||
protected SpelAwareProjectionInformation(Class<?> projectionType) {
|
||||
super(projectionType);
|
||||
}
|
||||
|
||||
if (!super.isInputProperty(descriptor)) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.projection.DefaultProjectionInformation#isInputProperty(java.beans.PropertyDescriptor)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isInputProperty(PropertyDescriptor descriptor) {
|
||||
|
||||
Method readMethod = descriptor.getReadMethod();
|
||||
|
||||
if (readMethod == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return AnnotationUtils.findAnnotation(readMethod, Value.class) == null;
|
||||
if (!super.isInputProperty(descriptor)) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Method readMethod = descriptor.getReadMethod();
|
||||
|
||||
if (readMethod == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return AnnotationUtils.findAnnotation(readMethod, Value.class) == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2015 the original author or authors.
|
||||
* Copyright 2008-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.
|
||||
@@ -37,6 +37,7 @@ import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
@@ -218,11 +219,29 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
|
||||
result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
|
||||
}
|
||||
|
||||
result.addAdvice(new QueryExecutorMethodInterceptor(information, customImplementation, target));
|
||||
ProjectionFactory projectionFactory = getProjectionFactory(classLoader, beanFactory);
|
||||
|
||||
result.addAdvice(new QueryExecutorMethodInterceptor(information, customImplementation, target, projectionFactory));
|
||||
|
||||
return (T) result.getProxy(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ProjectionFactory} to be used with the repository instances created.
|
||||
*
|
||||
* @param classLoader will never be {@literal null}.
|
||||
* @param beanFactory will never be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
protected ProjectionFactory getProjectionFactory(ClassLoader classLoader, BeanFactory beanFactory) {
|
||||
|
||||
SpelAwareProxyProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
factory.setBeanClassLoader(classLoader);
|
||||
factory.setBeanFactory(beanFactory);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link RepositoryMetadata} for the given repository interface.
|
||||
*
|
||||
@@ -401,7 +420,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
|
||||
* execution of repository interface methods.
|
||||
*/
|
||||
public QueryExecutorMethodInterceptor(RepositoryInformation repositoryInformation, Object customImplementation,
|
||||
Object target) {
|
||||
Object target, ProjectionFactory projectionFactory) {
|
||||
|
||||
Assert.notNull(repositoryInformation, "RepositoryInformation must not be null!");
|
||||
Assert.notNull(target, "Target must not be null!");
|
||||
@@ -427,13 +446,10 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
|
||||
return;
|
||||
}
|
||||
|
||||
SpelAwareProxyProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
factory.setBeanClassLoader(classLoader);
|
||||
factory.setBeanFactory(beanFactory);
|
||||
|
||||
for (Method method : queryMethods) {
|
||||
|
||||
RepositoryQuery query = lookupStrategy.resolveQuery(method, repositoryInformation, factory, namedQueries);
|
||||
RepositoryQuery query = lookupStrategy.resolveQuery(method, repositoryInformation, projectionFactory,
|
||||
namedQueries);
|
||||
|
||||
invokeListeners(query);
|
||||
queries.put(method, query);
|
||||
|
||||
+6
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* Copyright 2011-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.
|
||||
@@ -27,6 +27,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
@@ -45,13 +46,15 @@ public class QueryExecutorMethodInterceptorUnitTests {
|
||||
@Mock RepositoryInformation information;
|
||||
@Mock QueryLookupStrategy strategy;
|
||||
|
||||
ProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory();
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsRepositoryInterfaceWithQueryMethodsIfNoQueryLookupStrategyIsDefined() throws Exception {
|
||||
|
||||
when(information.getQueryMethods()).thenReturn(Arrays.asList(Object.class.getMethod("toString")));
|
||||
when(factory.getQueryLookupStrategy(any(Key.class))).thenReturn(null);
|
||||
|
||||
factory.new QueryExecutorMethodInterceptor(information, null, new Object());
|
||||
factory.new QueryExecutorMethodInterceptor(information, null, new Object(), projectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,7 +63,7 @@ public class QueryExecutorMethodInterceptorUnitTests {
|
||||
when(information.getQueryMethods()).thenReturn(Collections.<Method> emptySet());
|
||||
when(factory.getQueryLookupStrategy(any(Key.class))).thenReturn(strategy);
|
||||
|
||||
factory.new QueryExecutorMethodInterceptor(information, null, new Object());
|
||||
factory.new QueryExecutorMethodInterceptor(information, null, new Object(), projectionFactory);
|
||||
verify(strategy, times(0)).resolveQuery(any(Method.class), any(RepositoryMetadata.class),
|
||||
any(ProjectionFactory.class), any(NamedQueries.class));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user