Resolve @ReadPreference on actual repository interface.

Original pull request: #4545
Closes #4542
This commit is contained in:
Christoph Strobl
2023-11-02 15:21:08 +01:00
committed by Mark Paluch
parent db86097c0d
commit e78e1978d5
3 changed files with 71 additions and 8 deletions

View File

@@ -89,9 +89,12 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B
private final ConcurrentMap<Method, CrudMethodMetadata> metadataCache = new ConcurrentHashMap<>();
private final Set<Method> implementations = new HashSet<>();
private final RepositoryInformation repositoryInformation;
CrudMethodMetadataPopulatingMethodInterceptor(RepositoryInformation repositoryInformation) {
this.repositoryInformation = repositoryInformation;
ReflectionUtils.doWithMethods(repositoryInformation.getRepositoryInterface(), implementations::add,
method -> !repositoryInformation.isQueryMethod(method));
}
@@ -140,7 +143,7 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B
if (methodMetadata == null) {
methodMetadata = new DefaultCrudMethodMetadata(method);
methodMetadata = new DefaultCrudMethodMetadata(repositoryInformation.getRepositoryInterface(), method);
CrudMethodMetadata tmp = metadataCache.putIfAbsent(method, methodMetadata);
if (tmp != null) {
@@ -171,23 +174,24 @@ class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, B
/**
* Creates a new {@link DefaultCrudMethodMetadata} for the given {@link Method}.
*
* @param repositoryInterface the target repository interface.
* @param method must not be {@literal null}.
*/
DefaultCrudMethodMetadata(Method method) {
DefaultCrudMethodMetadata(Class<?> repositoryInterface, Method method) {
Assert.notNull(method, "Method must not be null");
this.readPreference = findReadPreference(method);
this.readPreference = findReadPreference(repositoryInterface, method);
}
private Optional<ReadPreference> findReadPreference(Method method) {
private Optional<ReadPreference> findReadPreference(Class<?> repositoryInterface, Method method) {
org.springframework.data.mongodb.repository.ReadPreference preference = AnnotatedElementUtils
.findMergedAnnotation(method, org.springframework.data.mongodb.repository.ReadPreference.class);
if (preference == null) {
preference = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(),
preference = AnnotatedElementUtils.findMergedAnnotation(repositoryInterface,
org.springframework.data.mongodb.repository.ReadPreference.class);
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2023 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.repository.support;
import static org.assertj.core.api.Assertions.*;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.data.mongodb.repository.Person;
import org.springframework.data.mongodb.repository.ReadPreference;
import org.springframework.data.mongodb.repository.support.CrudMethodMetadataPostProcessor.DefaultCrudMethodMetadata;
import org.springframework.data.repository.CrudRepository;
import org.springframework.util.ReflectionUtils;
/**
* @author Christoph Strobl
*/
class DefaultCrudMethodMetadataUnitTests {
@Test // GH-4542
void detectsReadPreferenceOnRepositoryInterface() {
DefaultCrudMethodMetadata metadata = new DefaultCrudMethodMetadata(ReadPreferenceAnnotated.class,
ReflectionUtils.findMethod(ReadPreferenceAnnotated.class, "findAll"));
assertThat(metadata.getReadPreference()).hasValue(com.mongodb.ReadPreference.primary());
}
@Test // GH-4542
void favorsReadPreferenceOfAnnotatedMethod() {
DefaultCrudMethodMetadata metadata = new DefaultCrudMethodMetadata(ReadPreferenceAnnotated.class,
ReflectionUtils.findMethod(ReadPreferenceAnnotated.class, "findById", Object.class));
assertThat(metadata.getReadPreference()).hasValue(com.mongodb.ReadPreference.secondary());
}
@ReadPreference("primary")
interface ReadPreferenceAnnotated extends CrudRepository<Person, String> {
@Override
@ReadPreference("secondary")
Optional<Person> findById(String s);
}
}

View File

@@ -152,7 +152,7 @@ public class SimpleMongoRepositoryUnitTests {
repository = new SimpleMongoRepository<>(entityInformation, mongoOperations);
repository.setRepositoryMethodMetadata(
new DefaultCrudMethodMetadata(TestRepositoryWithReadPreference.class.getMethod("dummy")));
new DefaultCrudMethodMetadata(TestRepositoryWithReadPreference.class, TestRepositoryWithReadPreference.class.getMethod("dummy")));
findCall.accept(repository);
@@ -167,7 +167,7 @@ public class SimpleMongoRepositoryUnitTests {
repository = new SimpleMongoRepository<>(entityInformation, mongoOperations);
repository.setRepositoryMethodMetadata(
new DefaultCrudMethodMetadata(TestRepositoryWithReadPreference.class.getMethod("dummy")));
new DefaultCrudMethodMetadata(TestRepositoryWithReadPreference.class, TestRepositoryWithReadPreference.class.getMethod("dummy")));
repository.findOne(Example.of(new TestDummy()));
@@ -188,7 +188,7 @@ public class SimpleMongoRepositoryUnitTests {
repository = new SimpleMongoRepository<>(entityInformation, mongoOperations);
repository.setRepositoryMethodMetadata(
new DefaultCrudMethodMetadata(TestRepositoryWithReadPreferenceMethod.class.getMethod("dummy")));
new DefaultCrudMethodMetadata(TestRepositoryWithReadPreferenceMethod.class, TestRepositoryWithReadPreferenceMethod.class.getMethod("dummy")));
repository.findBy(Example.of(new TestDummy()), FetchableFluentQuery::all);