diff --git a/src/main/java/org/springframework/data/projection/SpelAwareProxyProjectionFactory.java b/src/main/java/org/springframework/data/projection/SpelAwareProxyProjectionFactory.java index 5493d5e4d..b9d0968c0 100644 --- a/src/main/java/org/springframework/data/projection/SpelAwareProxyProjectionFactory.java +++ b/src/main/java/org/springframework/data/projection/SpelAwareProxyProjectionFactory.java @@ -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; + } } } diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java index 37630b894..1780c32b4 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java @@ -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); diff --git a/src/test/java/org/springframework/data/repository/core/support/QueryExecutorMethodInterceptorUnitTests.java b/src/test/java/org/springframework/data/repository/core/support/QueryExecutorMethodInterceptorUnitTests.java index 8d70e3d6e..5d541999e 100644 --- a/src/test/java/org/springframework/data/repository/core/support/QueryExecutorMethodInterceptorUnitTests.java +++ b/src/test/java/org/springframework/data/repository/core/support/QueryExecutorMethodInterceptorUnitTests.java @@ -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. 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)); }