问题描述
如果有人需要在Spring Data存储库上使用@Primary,请执行以下操作:看起来Spring Data JPA会忽略存储库上的@Primary
批注.
If someone ever needed to use @Primary on Spring Data repositories:It looks like Spring Data JPA ignores @Primary
annotations on repositories.
作为一种解决方法,我创建了BeanFactoryPostProcessor
,它检查给定的存储库是否具有@Primary
批注并将该bean设置为主.
As a workaround I have created BeanFactoryPostProcessor
which checks if given repository has @Primary
annotation and sets that bean as primary.
这是代码:
@Component
public class SpringDataPrimaryPostProcessor implements BeanFactoryPostProcessor {
public static final String REPOSITORY_INTERFACE_PROPERTY = "repositoryInterface";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
makeRepositoriesPrimary(getRepositoryBeans(beanFactory));
}
protected List<BeanDefinition> getRepositoryBeans(ConfigurableListableBeanFactory beanFactory) {
List<BeanDefinition> springDataRepositoryDefinitions = Lists.newArrayList();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
String beanClassName = beanDefinition.getBeanClassName();
try {
Class<?> beanClass = Class.forName(beanClassName);
if (isSpringDataJpaRepository(beanClass)) {
springDataRepositoryDefinitions.add(beanDefinition);
}
} catch (ClassNotFoundException e) {
throw new ApplicationContextException(String.format("Error when trying to create instance of %s", beanClassName), e);
}
}
return springDataRepositoryDefinitions;
}
protected void makeRepositoriesPrimary(List<BeanDefinition> repositoryBeans) {
for (BeanDefinition repositoryBeanDefinition : repositoryBeans) {
String repositoryInterface = (String) repositoryBeanDefinition.getPropertyValues().get(REPOSITORY_INTERFACE_PROPERTY);
if (isPrimary(repositoryInterface)) {
log.debug("Making site repository bean primary, class: {}", repositoryInterface);
repositoryBeanDefinition.setPrimary(true);
}
}
}
protected boolean isSpringDataJpaRepository(Class<?> beanClass) {
return RepositoryFactoryInformation.class.isAssignableFrom(beanClass);
}
private boolean isPrimary(String repositoryInterface) {
return AnnotationUtils.findAnnotation(getClassSafely(repositoryInterface), Primary.class) != null;
}
private Class<?> getClassSafely(String repositoryInterface) {
try {
return Class.forName(repositoryInterface);
} catch (ClassNotFoundException e) {
throw new ApplicationContextException(String.format("Error when trying to create instance of %s", repositoryInterface), e);
}
}
推荐答案
我尝试将解决方案应用于具有两个Mongo存储库的Spring Boot应用程序.但是它无法在propertyValues中找到repositoryInterface
.进一步的调查表明,有一个属性可以标识存储库接口factoryBeanObjectType
.
I tried applying the solution to spring boot application having two Mongo repositories.But it was not able to find repositoryInterface
in propertyValues.Further investigation revealed that there is an attribute to identify the repository interface factoryBeanObjectType
.
因此,从以下位置更改方法makeRepositoriesPrimary()
中的代码:
So changing the code in method makeRepositoriesPrimary()
from:
String repositoryInterface = (String) repositoryBeanDefinition.getPropertyValues().get(REPOSITORY_INTERFACE_PROPERTY);
收件人:
String repositoryInterface = (String) repositoryBeanDefinition.getAttribute("factoryBeanObjectType");
按预期工作.
希望这会有所帮助.
这篇关于在Spring Data JPA存储库中使用@Primary的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!