如果有人需要在Spring Data repositories上使用@Primary :看起来Spring Data JPA忽略了存储库上的@Primary注释。
作为一种变通方法,我创建了BeanFactoryPostProcessor,它检查给定的存储库是否有@Primary注释,并将该bean设置为主要bean。
代码如下:
@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);
}
}发布于 2019-07-05 23:15:26
我尝试将该解决方案应用于具有两个Mongo存储库的spring boot应用程序。但它无法在propertyValues中找到repositoryInterface。进一步的调查发现,有一个属性可以标识存储库接口factoryBeanObjectType。
因此,将方法makeRepositoriesPrimary()中的代码从:
String repositoryInterface = (String) repositoryBeanDefinition.getPropertyValues().get(REPOSITORY_INTERFACE_PROPERTY);至:
String repositoryInterface = (String) repositoryBeanDefinition.getAttribute("factoryBeanObjectType");和预期的一样。
希望这能有所帮助。
https://stackoverflow.com/questions/30029878
复制相似问题