Я задал несколько вопросов в разделе комментариев этой темы.
Во время отладки приложения я заметил некоторые возможные ошибки кода. Это баги или фичи?
- В
ExpressionEvaluatingRequestHandlerAdvice::evaluateSuccessExpression
исключение генерируется после того, какAdviceMessage
отправляется вSuccessChannel
. Это вызывает в нем полезную нагрузку Exception. Разве метод не должен сначала генерировать исключение, если оно есть? - В том же классе
propagateOnSuccessEvaluationFailures
по умолчанию имеет значение false, что приводит к тому, что исключения не выдаются. Это скорее сводит на нет цельFailChannel
. Я установил его на «истину» извне. Не могли бы вы объяснить мыслительный процесс, стоящий за этим?
Гэри ответил,
Я не понимаю ваш пункт 1. Что касается пункта 2., как правило, обработчик ошибок обрабатывает ошибку, и вызывающему абоненту не нужно знать, что возникла проблема. Если есть, то, как правило, поток обработчика ошибок должен генерировать новое исключение, чтобы указать вызывающей стороне, что обработчик ошибок был задействован. Логическое значение предназначено для редкого случая, когда вы хотите обработать ошибку, а также выдать исходное исключение вызывающей стороне.
Чтобы не захламлять эту ветку, мы можем обсудить вопросы здесь.
Я думаю, объяснение пункта 2 применимо для trapException
.
Чтобы было понятно, я скопировал часть ExpressionEvaluatingRequestHandlerAdvice
.
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
try {
Object e = callback.execute();
if(this.onSuccessExpression != null) {
this.evaluateSuccessExpression(message);
}
return e;
} catch (Exception var7) {
Exception actualException = this.unwrapExceptionIfNecessary(var7);
if(this.onFailureExpression != null) {
Object evalResult = this.evaluateFailureExpression(message, actualException);
if(this.returnFailureExpressionResult) {
return evalResult;
}
}
if(!this.trapException) {
throw actualException;
} else {
return null;
}
}
}
private void evaluateSuccessExpression(Message<?> message) throws Exception {
boolean evaluationFailed = false;
Object evalResult;
try {
evalResult = this.onSuccessExpression.getValue(this.prepareEvaluationContextToUse((Exception)null), message);
} catch (Exception var5) {
evalResult = var5;
evaluationFailed = true;
}
if(this.successChannel == null && this.successChannelName != null && this.getChannelResolver() != null) {
this.successChannel = (MessageChannel)this.getChannelResolver().resolveDestination(this.successChannelName);
}
if(evalResult != null && this.successChannel != null) {
AdviceMessage resultMessage = new AdviceMessage(evalResult, message);
this.messagingTemplate.send(this.successChannel, resultMessage);
}
if(evaluationFailed && this.propagateOnSuccessEvaluationFailures) {
throw (Exception)evalResult;
}
}
private Object evaluateFailureExpression(Message<?> message, Exception exception) throws Exception {
Object evalResult;
try {
evalResult = this.onFailureExpression.getValue(this.prepareEvaluationContextToUse(exception), message);
} catch (Exception var6) {
evalResult = var6;
this.logger.error("Failure expression evaluation failed for " + message + ": " + var6.getMessage());
}
if(this.failureChannel == null && this.failureChannelName != null && this.getChannelResolver() != null) {
this.failureChannel = (MessageChannel)this.getChannelResolver().resolveDestination(this.failureChannelName);
}
if(evalResult != null && this.failureChannel != null) {
ExpressionEvaluatingRequestHandlerAdvice.MessageHandlingExpressionEvaluatingAdviceException messagingException = new ExpressionEvaluatingRequestHandlerAdvice.MessageHandlingExpressionEvaluatingAdviceException(message, "Handler Failed", this.unwrapThrowableIfNecessary(exception), evalResult);
ErrorMessage resultMessage = new ErrorMessage(messagingException);
this.messagingTemplate.send(this.failureChannel, resultMessage);
}
return evalResult;
}
В doInvoke
вызывается evaluateFailureExpression
, если callback.execute()
или evaluateSuccessExpression
вызывает исключение.
Теперь в evaluateSuccessExpression
, если при оценке SuccessExpression
возникает какая-либо ошибка, исключение сохраняется в evalResult
. Это отправляется на SuccessChannel
, если это настроено. Если propagateOnSuccessEvaluationFailures
установлено на true
, то только evaluateSuccessExpression
выдает ошибку. Поскольку по умолчанию установлено значение «false», evalResult
не выбрасывается и, следовательно, не перехватывается evaluateFailureExpression
.
Даже если propagateOnSuccessEvaluationFailures
необходимо установить на «false» по другим требованиям, проверка на исключение должна быть до отправки результата в SuccessChannel
.