Ensure unique bean definitions for EntityManager beans.
We now make sure to create unique beans to avoid autowiring resolution problems for EntityManager beans through SharedEntityManagerCreator definitions. Closes #2699
This commit is contained in:
@@ -38,7 +38,6 @@ import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
@@ -164,7 +163,7 @@ public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensi
|
||||
|
||||
super.registerBeansForRoot(registry, config);
|
||||
|
||||
prepareAndRegisterSharedEntityManger(registry, config);
|
||||
registerSharedEntityMangerIfNotAlreadyRegistered(registry, config);
|
||||
|
||||
Object source = config.getSource();
|
||||
|
||||
@@ -208,18 +207,24 @@ public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensi
|
||||
}, registry, JpaEvaluationContextExtension.class.getName(), source);
|
||||
}
|
||||
|
||||
private String prepareAndRegisterSharedEntityManger(BeanDefinitionRegistry registry,
|
||||
private String registerSharedEntityMangerIfNotAlreadyRegistered(BeanDefinitionRegistry registry,
|
||||
RepositoryConfigurationSource config) {
|
||||
|
||||
AbstractBeanDefinition entityManager = getEntityManagerBeanDefinitionFor(config, null);
|
||||
entityManager.setRole(BeanDefinition.ROLE_SUPPORT);
|
||||
entityManager.setSynthetic(true);
|
||||
entityManager.setPrimary(false);
|
||||
entityManager.setAutowireCandidate(false);
|
||||
String entityManagerBeanRef = getEntityManagerBeanRef(config);
|
||||
String entityManagerBeanName = "jpaSharedEM_" + entityManagerBeanRef;
|
||||
|
||||
if (!registry.containsBeanDefinition(entityManagerBeanName)) {
|
||||
|
||||
AbstractBeanDefinition entityManager = getEntityManagerBeanDefinitionFor(config, null);
|
||||
entityManager.setRole(BeanDefinition.ROLE_SUPPORT);
|
||||
entityManager.setSynthetic(true);
|
||||
entityManager.setPrimary(false);
|
||||
entityManager.setAutowireCandidate(false);
|
||||
|
||||
registry.registerBeanDefinition(entityManagerBeanName, entityManager);
|
||||
}
|
||||
|
||||
String entityManagerBeanName = BeanDefinitionReaderUtils.uniqueBeanName("jpaSharedEM", registry);
|
||||
entityManagerRefs.put(config, entityManagerBeanName);
|
||||
registry.registerBeanDefinition(entityManagerBeanName, entityManager);
|
||||
return entityManagerBeanName;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.data.jpa.util.BeanDefinitionUtils.*;
|
||||
import org.springframework.orm.jpa.SharedEntityManagerCreator;
|
||||
|
||||
/**
|
||||
@@ -44,6 +42,7 @@ import org.springframework.orm.jpa.SharedEntityManagerCreator;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Réda Housni Alaoui
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class EntityManagerBeanDefinitionRegistrarPostProcessor implements BeanFactoryPostProcessor, Ordered {
|
||||
|
||||
@@ -59,7 +58,7 @@ public class EntityManagerBeanDefinitionRegistrarPostProcessor implements BeanFa
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurableListableBeanFactory factory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
ConfigurableListableBeanFactory factory = beanFactory;
|
||||
|
||||
for (EntityManagerFactoryBeanDefinition definition : getEntityManagerFactoryBeanDefinitions(factory)) {
|
||||
|
||||
@@ -69,22 +68,27 @@ public class EntityManagerBeanDefinitionRegistrarPostProcessor implements BeanFa
|
||||
continue;
|
||||
}
|
||||
|
||||
String entityManagerBeanName = "jpaSharedEM_AWC_" + definition.getBeanName();
|
||||
BeanDefinitionRegistry definitionRegistry = (BeanDefinitionRegistry) definitionFactory;
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator");
|
||||
builder.setFactoryMethod("createSharedEntityManager");
|
||||
builder.addConstructorArgReference(definition.getBeanName());
|
||||
if (!beanFactory.containsBeanDefinition(entityManagerBeanName)
|
||||
&& !definitionRegistry.containsBeanDefinition(entityManagerBeanName)) {
|
||||
|
||||
AbstractBeanDefinition emBeanDefinition = builder.getRawBeanDefinition();
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator");
|
||||
builder.setFactoryMethod("createSharedEntityManager");
|
||||
builder.addConstructorArgReference(definition.getBeanName());
|
||||
|
||||
emBeanDefinition.setPrimary(definition.getBeanDefinition().isPrimary());
|
||||
emBeanDefinition.addQualifier(new AutowireCandidateQualifier(Qualifier.class, definition.getBeanName()));
|
||||
emBeanDefinition.setScope(definition.getBeanDefinition().getScope());
|
||||
emBeanDefinition.setSource(definition.getBeanDefinition().getSource());
|
||||
emBeanDefinition.setLazyInit(true);
|
||||
AbstractBeanDefinition emBeanDefinition = builder.getRawBeanDefinition();
|
||||
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(emBeanDefinition, definitionRegistry);
|
||||
emBeanDefinition.setPrimary(definition.getBeanDefinition().isPrimary());
|
||||
emBeanDefinition.addQualifier(new AutowireCandidateQualifier(Qualifier.class, definition.getBeanName()));
|
||||
emBeanDefinition.setScope(definition.getBeanDefinition().getScope());
|
||||
emBeanDefinition.setSource(definition.getBeanDefinition().getSource());
|
||||
emBeanDefinition.setLazyInit(true);
|
||||
|
||||
definitionRegistry.registerBeanDefinition(entityManagerBeanName, emBeanDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Jens Schauder
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class EntityManagerBeanDefinitionRegistrarPostProcessorUnitTests {
|
||||
|
||||
@@ -65,6 +66,24 @@ public class EntityManagerBeanDefinitionRegistrarPostProcessorUnitTests {
|
||||
assertThat(beanFactory.getBeanDefinitionCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // gh-2699
|
||||
void avoidsDuplicateBeanRegistrations() {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(StubEntityManagerFactoryBean.class);
|
||||
builder.addConstructorArgValue(SpecialEntityManagerFactory.class);
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerBeanDefinition("factory", builder.getBeanDefinition());
|
||||
|
||||
beanFactory.registerBeanDefinition("jpaSharedEM_AWC_factory",
|
||||
BeanDefinitionBuilder.rootBeanDefinition(Object.class).getBeanDefinition());
|
||||
|
||||
BeanFactoryPostProcessor processor = new EntityManagerBeanDefinitionRegistrarPostProcessor();
|
||||
processor.postProcessBeanFactory(beanFactory);
|
||||
|
||||
assertThat(beanFactory.getBeanDefinitionCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
interface SpecialEntityManagerFactory extends EntityManagerFactory {}
|
||||
|
||||
static class StubEntityManagerFactoryBean extends LocalContainerEntityManagerFactoryBean {
|
||||
|
||||
Reference in New Issue
Block a user