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 350c55b99..dbcaf1958 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; @@ -39,6 +40,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. @@ -48,9 +50,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) @@ -65,14 +77,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 96cb0b531..2f2c3930d 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 @@ -42,7 +42,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}. @@ -55,9 +55,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); } /* @@ -68,7 +78,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { protected Object getTargetRepository(RepositoryMetadata metadata) { SimpleJpaRepository repository = getTargetRepository(metadata, 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 c470443d7..fe92b61f7 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}. @@ -152,6 +155,20 @@ public class JpaRepositoryFactoryUnitTests { } } + /** + * @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