Цель состоит в том, чтобы обработать все постоянные исключения и перейти к простому общему исключению, чтобы сервисный уровень мог легко их обработать.
Решение состоит в том, чтобы использовать AOP для перехвата исключения из реализации DAO. Вот весенняя конфигурация:
<bean id="DBExceptions" class="com.dao.impl.DAOExceptionTranslator" />
<aop:config>
<aop:aspect id="dbExceptionsAspect" ref="DBExceptions">
<aop:after-throwing throwing="ex"
pointcut="execution(* com.dao.impl.*.*(*))" method="doDAOActions" />
</aop:aspect>
</aop:config>
Вот реализация DAO:
@Transactional
public class UserDAOImpl extends GenericDAOImpl implements UserDAO {
@PersistenceContext
protected EntityManager entityManager;
@Override
public User findUserByUsername(String username) throws DAOException {
Query query = entityManager
.createQuery("select u from User u where u.username=:username");
query.setParameter("username", username);
Object userObject = query.getSingleResult();
return (User) userObject;
}
А вот код для использования DAO:
private UserDAO userDAO;
public User getUserById(int id) throws UserServiceException {
try {
Object user = userDAO.findById(User.class, id);
...
Реализация userDAO внедряется пружиной, но для обычного исключения из базы данных она может быть перехвачена, а для исключения соединения она не выполнена.
Я думаю, потому что до того, как весна внедрила реализацию DAO, она сначала создаст соединение, и это не удалось, поэтому она не вызывает целевую операцию.
Я хочу перехватить все исключения из DAO, как решить побочный эффект прокси с помощью пружинного впрыска.
вот два разных стека:
Логическая ошибка в БД:
UserDAOImpl.findUserByUsername(String) line: 23
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 309
ReflectiveMethodInvocation.invokeJoinpoint() line: 183
ReflectiveMethodInvocation.proceed() line: 150
AspectJAfterThrowingAdvice.invoke(MethodInvocation) line: 55
ReflectiveMethodInvocation.proceed() line: 172
TransactionInterceptor.invoke(MethodInvocation) line: 110
ReflectiveMethodInvocation.proceed() line: 172
ExposeInvocationInterceptor.invoke(MethodInvocation) line: 89
ReflectiveMethodInvocation.proceed() line: 172
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 202
$Proxy17.findUserByUsername(String) line: not available
UserService.getUser(String) line: 74
Но если это ошибка соединения с БД:
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:382)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy17.findUserByUsername(Unknown Source)
at com.service.UserService.getUser(UserService.java:74)
Как решить проблему?
Решение состоит в том, чтобы указать последовательность каждого прокси, изменение:
<aop:config>
<aop:aspect id="dbExceptionsAspect" ref="DBExceptions" order="1">
<aop:after-throwing throwing="ex"
pointcut="execution(* com.dao.impl.*.*(*))" method="doDAOActions" />
</aop:aspect>
</aop:config>
После добавления порядка ключевых слов сначала будет вызван прокси DBExceptions, см. Стек после изменения.
DAOExceptionTranslator.doDAOActions(Exception) line: 12
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
AspectJAfterThrowingAdvice(AbstractAspectJAdvice).invokeAdviceMethodWithGivenArgs(Object[]) line: 621
AspectJAfterThrowingAdvice(AbstractAspectJAdvice).invokeAdviceMethod(JoinPointMatch, Object, Throwable) line: 603
AspectJAfterThrowingAdvice.invoke(MethodInvocation) line: 59
ReflectiveMethodInvocation.proceed() line: 172
ExposeInvocationInterceptor.invoke(MethodInvocation) line: 89
ReflectiveMethodInvocation.proceed() line: 172
JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 202
$Proxy17.findUserByUsername(String) line: not available
UserService.getUser(String) line: 74