diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java index 50f7635eb..6a71cdac0 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupport.java @@ -15,6 +15,7 @@ */ package org.springframework.data.repository.core.support; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -71,6 +72,7 @@ public abstract class RepositoryFactoryBeanSupport, private BeanFactory beanFactory; private boolean lazyInit = false; private Optional evaluationContextProvider = Optional.empty(); + private List repositoryFactoryCustomizers = new ArrayList<>(); private ApplicationEventPublisher publisher; private Lazy repository; @@ -154,6 +156,19 @@ public abstract class RepositoryFactoryBeanSupport, this.evaluationContextProvider = Optional.of(evaluationContextProvider); } + /** + * Register a {@link RepositoryFactoryCustomizer} to customize the {@link RepositoryFactorySupport repository factor} + * before creating the repository. + * + * @param customizer must not be {@literal null}. + * @since 2.4 + */ + public void addRepositoryFactoryCustomizer(RepositoryFactoryCustomizer customizer) { + + Assert.notNull(customizer, "RepositoryFactoryCustomizer must not be null"); + this.repositoryFactoryCustomizers.add(customizer); + } + /** * Configures whether to initialize the repository proxy lazily. This defaults to {@literal false}. * @@ -293,6 +308,8 @@ public abstract class RepositoryFactoryBeanSupport, repositoryBaseClass.ifPresent(this.factory::setRepositoryBaseClass); + this.repositoryFactoryCustomizers.forEach(customizer -> customizer.customize(this.factory)); + RepositoryFragments customImplementationFragment = customImplementation // .map(RepositoryFragments::just) // .orElseGet(RepositoryFragments::empty); diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryCustomizer.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryCustomizer.java new file mode 100644 index 000000000..db566ae14 --- /dev/null +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactoryCustomizer.java @@ -0,0 +1,32 @@ +/* + * Copyright 2020 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.repository.core.support; + +/** + * Callback interface that can be used to to customize a {@link RepositoryFactorySupport repository factory}. + * + * @author Mark Paluch + * @since 2.4 + */ +public interface RepositoryFactoryCustomizer { + + /** + * Callback to customize a {@link RepositoryFactorySupport} instance. + * + * @param repositoryFactory repository factory to customize. + */ + void customize(RepositoryFactorySupport repositoryFactory); +} diff --git a/src/test/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupportUnitTests.java b/src/test/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupportUnitTests.java index d74f14cd7..3dea5cb8c 100755 --- a/src/test/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupportUnitTests.java +++ b/src/test/java/org/springframework/data/repository/core/support/RepositoryFactoryBeanSupportUnitTests.java @@ -18,6 +18,11 @@ package org.springframework.data.repository.core.support; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; import org.junit.jupiter.api.Test; import org.springframework.data.querydsl.QuerydslPredicateExecutor; @@ -69,6 +74,29 @@ class RepositoryFactoryBeanSupportUnitTests { assertThat(information.getQueryMethods()).isEmpty(); } + @Test // DATACMNS-1688 + void customizesRepositoryFactory() { + + RepositoryFactoryBeanSupport factoryBean = // + new DummyRepositoryFactoryBean<>(SampleRepository.class); + factoryBean.addRepositoryFactoryCustomizer(repositoryFactory -> repositoryFactory + .addRepositoryProxyPostProcessor((factory, repositoryInformation) -> factory.addAdvice(new MethodInterceptor() { + @Nullable + @Override + public Object invoke(@Nonnull MethodInvocation invocation) { + throw new UnsupportedOperationException(); + } + }))); + factoryBean.afterPropertiesSet(); + + try { + factoryBean.getObject().someMethod(); + fail("Missing UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + // all good + } + } + @Test // DATACMNS-1345 void reportsMappingContextUnavailableForPersistentEntityLookup() { @@ -87,7 +115,11 @@ class RepositoryFactoryBeanSupportUnitTests { .isThrownBy(() -> bean.getPersistentEntity()); } - interface SampleRepository extends Repository {} + interface SampleRepository extends Repository { + + void someMethod(); + + } interface SampleWithQuerydslRepository extends Repository, QuerydslPredicateExecutor {} }