diff --git a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java index 3eb164d56..a0cdd48a7 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java @@ -30,6 +30,7 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.interceptor.ExposeInvocationInterceptor; import org.springframework.aop.target.AbstractLazyCreationTargetSource; +import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.Lock; @@ -38,6 +39,7 @@ import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * {@link RepositoryProxyPostProcessor} that sets up interceptors to read metadata information from the invoked method. @@ -47,9 +49,19 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @author Thomas Darimont */ -enum CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor { +class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, BeanClassLoaderAware { - INSTANCE; + private ClassLoader classLoader = ClassUtils.getDefaultClassLoader(); + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang.ClassLoader) + */ + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader == null ? ClassUtils.getDefaultClassLoader() : classLoader; + + } /* * (non-Javadoc) @@ -64,14 +76,14 @@ enum CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor { * Returns a {@link CrudMethodMetadata} proxy that will lookup the actual target object by obtaining a thread bound * instance from the {@link TransactionSynchronizationManager} later. */ - public CrudMethodMetadata getLockMetadataProvider() { + public CrudMethodMetadata getCrudMethodMetadata() { ProxyFactory factory = new ProxyFactory(); factory.addInterface(CrudMethodMetadata.class); factory.setTargetSource(new ThreadBoundTargetSource()); - return (CrudMethodMetadata) factory.getProxy(); + return (CrudMethodMetadata) factory.getProxy(this.classLoader); } /** diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java index 15209a7a4..01eb14543 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java @@ -43,7 +43,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { private final EntityManager entityManager; private final QueryExtractor extractor; - private final CrudMethodMetadataPostProcessor lockModePostProcessor; + private final CrudMethodMetadataPostProcessor crudMethodMetadataPostProcessor; /** * Creates a new {@link JpaRepositoryFactory}. @@ -56,9 +56,19 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { this.entityManager = entityManager; this.extractor = PersistenceProvider.fromEntityManager(entityManager); - this.lockModePostProcessor = CrudMethodMetadataPostProcessor.INSTANCE; + this.crudMethodMetadataPostProcessor = new CrudMethodMetadataPostProcessor(); - addRepositoryProxyPostProcessor(lockModePostProcessor); + addRepositoryProxyPostProcessor(crudMethodMetadataPostProcessor); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#setBeanClassLoader(java.lang.ClassLoader) + */ + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + super.setBeanClassLoader(classLoader); + this.crudMethodMetadataPostProcessor.setBeanClassLoader(classLoader); } /* @@ -69,7 +79,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { protected Object getTargetRepository(RepositoryInformation information) { SimpleJpaRepository repository = getTargetRepository(information, entityManager); - repository.setRepositoryMethodMetadata(lockModePostProcessor.getLockMetadataProvider()); + repository.setRepositoryMethodMetadata(crudMethodMetadataPostProcessor.getCrudMethodMetadata()); return repository; } diff --git a/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryUnitTests.java index 444658cdb..bb76e1b58 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryUnitTests.java @@ -31,6 +31,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.aop.framework.Advised; +import org.springframework.core.OverridingClassLoader; import org.springframework.data.jpa.domain.sample.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.custom.CustomGenericJpaRepositoryFactory; @@ -38,7 +39,9 @@ import org.springframework.data.jpa.repository.custom.UserCustomExtendedReposito import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; import org.springframework.data.repository.query.QueryLookupStrategy.Key; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ClassUtils; /** * Unit test for {@code JpaRepositoryFactory}. @@ -164,6 +167,20 @@ public class JpaRepositoryFactoryUnitTests { assertEquals(CustomJpaRepository.class, ((Advised) repository).getTargetClass()); } + /** + * @see DATAJPA-819 + */ + @Test + public void crudMethodMetadataPostProcessorUsesBeanClassLoader() { + + ClassLoader classLoader = new OverridingClassLoader(ClassUtils.getDefaultClassLoader()); + + factory.setBeanClassLoader(classLoader); + + Object processor = ReflectionTestUtils.getField(factory, "crudMethodMetadataPostProcessor"); + assertThat(ReflectionTestUtils.getField(processor, "classLoader"), is((Object) classLoader)); + } + private interface SimpleSampleRepository extends JpaRepository { @Transactional