Sort detected PersistenceExceptionTranslator beans
Closes gh-24644
This commit is contained in:
parent
b345019415
commit
14839b1f4a
|
|
@ -16,15 +16,12 @@
|
|||
|
||||
package org.springframework.dao.support;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
|
@ -147,7 +144,8 @@ public class PersistenceExceptionTranslationInterceptor
|
|||
else {
|
||||
PersistenceExceptionTranslator translator = this.persistenceExceptionTranslator;
|
||||
if (translator == null) {
|
||||
Assert.state(this.beanFactory != null, "Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory");
|
||||
Assert.state(this.beanFactory != null,
|
||||
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory");
|
||||
translator = detectPersistenceExceptionTranslators(this.beanFactory);
|
||||
this.persistenceExceptionTranslator = translator;
|
||||
}
|
||||
|
|
@ -158,20 +156,15 @@ public class PersistenceExceptionTranslationInterceptor
|
|||
|
||||
/**
|
||||
* Detect all PersistenceExceptionTranslators in the given BeanFactory.
|
||||
* @param beanFactory the ListableBeanFactory to obtaining all
|
||||
* PersistenceExceptionTranslators from
|
||||
* @param bf the ListableBeanFactory to obtain PersistenceExceptionTranslators from
|
||||
* @return a chained PersistenceExceptionTranslator, combining all
|
||||
* PersistenceExceptionTranslators found in the factory
|
||||
* PersistenceExceptionTranslators found in the given bean factory
|
||||
* @see ChainedPersistenceExceptionTranslator
|
||||
*/
|
||||
protected PersistenceExceptionTranslator detectPersistenceExceptionTranslators(ListableBeanFactory beanFactory) {
|
||||
protected PersistenceExceptionTranslator detectPersistenceExceptionTranslators(ListableBeanFactory bf) {
|
||||
// Find all translators, being careful not to activate FactoryBeans.
|
||||
Map<String, PersistenceExceptionTranslator> pets = BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
beanFactory, PersistenceExceptionTranslator.class, false, false);
|
||||
ChainedPersistenceExceptionTranslator cpet = new ChainedPersistenceExceptionTranslator();
|
||||
for (PersistenceExceptionTranslator pet : pets.values()) {
|
||||
cpet.addDelegate(pet);
|
||||
}
|
||||
bf.getBeanProvider(PersistenceExceptionTranslator.class, false).orderedStream().forEach(cpet::addDelegate);
|
||||
return cpet;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,19 +16,35 @@
|
|||
|
||||
package org.springframework.dao.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslationInterceptor;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for standalone usage of a PersistenceExceptionTranslationInterceptor, as explicit advice bean in a BeanFactory
|
||||
* rather than applied as part of a PersistenceExceptionTranslationAdvisor.
|
||||
* Tests for standalone usage of a PersistenceExceptionTranslationInterceptor,
|
||||
* as explicit advice bean in a BeanFactory rather than applied as part of a
|
||||
* PersistenceExceptionTranslationAdvisor.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Tadaya Tsuyukubo
|
||||
*/
|
||||
public class PersistenceExceptionTranslationInterceptorTests extends PersistenceExceptionTranslationAdvisorTests {
|
||||
|
||||
|
|
@ -42,4 +58,52 @@ public class PersistenceExceptionTranslationInterceptorTests extends Persistence
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectPersistenceExceptionTranslators() throws Throwable {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
|
||||
bf.registerBeanDefinition("peti", new RootBeanDefinition(PersistenceExceptionTranslationInterceptor.class));
|
||||
|
||||
List<Integer> callOrder = new ArrayList<>();
|
||||
bf.registerSingleton("pet20", new CallOrderAwareExceptionTranslator(20, callOrder));
|
||||
bf.registerSingleton("pet10", new CallOrderAwareExceptionTranslator(10, callOrder));
|
||||
bf.registerSingleton("pet30", new CallOrderAwareExceptionTranslator(30, callOrder));
|
||||
|
||||
PersistenceExceptionTranslationInterceptor interceptor =
|
||||
bf.getBean("peti", PersistenceExceptionTranslationInterceptor.class);
|
||||
interceptor.setAlwaysTranslate(true);
|
||||
|
||||
RuntimeException exception = new RuntimeException();
|
||||
MethodInvocation invocation = mock(MethodInvocation.class);
|
||||
given(invocation.proceed()).willThrow(exception);
|
||||
|
||||
assertThatThrownBy(() -> interceptor.invoke(invocation)).isSameAs(exception);
|
||||
|
||||
assertThat(callOrder).containsExactly(10, 20, 30);
|
||||
}
|
||||
|
||||
|
||||
private static class CallOrderAwareExceptionTranslator implements PersistenceExceptionTranslator, Ordered {
|
||||
|
||||
private final int order;
|
||||
|
||||
private final List<Integer> callOrder;
|
||||
|
||||
public CallOrderAwareExceptionTranslator(int order, List<Integer> callOrder) {
|
||||
this.order = order;
|
||||
this.callOrder = callOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
callOrder.add(this.order);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue