外部异常转换为框架内部异常的实例:
RabbitExceptionTranslator把IOException、UnsupportedEncodingException、ConnectException和TimeoutException等转换为Rabbit框架内部异常
package org.springframework.amqp.rabbit.support;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.util.concurrent.TimeoutException;
import org.springframework.amqp.AmqpAuthenticationException;
import org.springframework.amqp.AmqpConnectException;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.AmqpIOException;
import org.springframework.amqp.AmqpTimeoutException;
import org.springframework.amqp.AmqpUnsupportedEncodingException;
import org.springframework.amqp.UncategorizedAmqpException;
import org.springframework.util.Assert;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.PossibleAuthenticationFailureException;
import com.rabbitmq.client.ShutdownSignalException;
/**
* Translates Rabbit Exceptions to the {@link AmqpException} class
* hierarchy.
* This functionality was previously in RabbitUtils, but that
* caused a package tangle.
*
* @author Gary Russell
* @since 1.2
*
*/
public final class RabbitExceptionTranslator {
private RabbitExceptionTranslator() {
}
public static RuntimeException convertRabbitAccessException(Throwable ex) {
Assert.notNull(ex, "Exception must not be null");
if (ex instanceof AmqpException) {
return (AmqpException) ex;
}
if (ex instanceof ShutdownSignalException) {
return new AmqpConnectException((ShutdownSignalException) ex);
}
if (ex instanceof ConnectException) {
return new AmqpConnectException((ConnectException) ex);
}
if (ex instanceof PossibleAuthenticationFailureException) {
return new AmqpAuthenticationException(ex);
}
if (ex instanceof UnsupportedEncodingException) {
return new AmqpUnsupportedEncodingException(ex);
}
if (ex instanceof IOException) {
return new AmqpIOException((IOException) ex);
}
if (ex instanceof TimeoutException) {
return new AmqpTimeoutException(ex);
}
if (ex instanceof ConsumerCancelledException) {
return new org.springframework.amqp.rabbit.support.ConsumerCancelledException(ex);
}
if (ex instanceof org.springframework.amqp.rabbit.support.ConsumerCancelledException) {
return (org.springframework.amqp.rabbit.support.ConsumerCancelledException) ex;
}
// fallback
return new UncategorizedAmqpException(ex);
}
}
另外一个问题,为什么要这样转换呢?
下面找几个引用convertRabbitAccessException方法的地方看看。
org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer#stop()
@Override
public void stop() {
try {
doStop();
}
catch (Exception ex) {
throw convertRabbitAccessException(ex);
}
finally {
synchronized (this.lifecycleMonitor) {
this.running = false;
this.lifecycleMonitor.notifyAll();
}
}
}
org.springframework.amqp.rabbit.core.RabbitTemplate#doExecute
try {
return invokeAction(action, connectionFactory, channel);
}
catch (Exception ex) {
if (isChannelLocallyTransacted(channel)) {
resourceHolder.rollbackAll();
}
throw convertRabbitAccessException(ex);
}
原来是为了方便异常的捕获,都是同一抛出Exception,然后调用convertRabbitAccessException方法统一转换对应的异常。实现代码的复用。