ひよっこ。

I want to…

SpringのexceptionResolver設定時の挙動

Posted by hikaruworld : 2010 12月 28

ちょっと勘違いしていてハマったもので。
これで問題ないかは自信なし…

SpringのExceptionResoloverは起動時にBeanFactoryを舐めて、
HandlerExceptionResolverに連なる実装クラスを自動でロードしてくれるみたいです。

但し、exceptionResoloverを定義した場合、
つまり明示的にHandlerExceptionResolverを継承したクラスを読み込んだ場合、
exceptionResolverで定義したインスタンスしか読み込みしなくなるみたいですね。

というわけで、Spring3.0で追加された各種ExceptionHandler
(DefaultHandlerExceptionResolver,AnnotationMethodHandlerExceptionResolver,ResponseStatusExceptionResolver)
と併用して利用したい場合は、こんな感じで設定しておけばOKみたいです。
※何も設定しない場合、上記3種のExceptionHandlerはDispatcherServlet読み込み時にデフォルトで有効になっています。

余計なことするなってことですかね。

デフォルト設定とSimpleMappingExceptionResoloverを有効にする

<!-- デフォルトの設定を明示的に読み込む -->
<bean name="defaultHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver" />
<bean name="annotationMethodHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver" />
<bean name="responseStatusExceptionResolver" class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver" />
<!-- SimpleMappingExceptionResoloverを読み込む -->
<bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<!-- 適当に設定を書く -->
	<property name="defaultErrorView"  value="/errors/error"/>
</bean>

ちょっとソースを

ちなみに、DispatcherServlet側の読み込み処理はこんな感じです。

private void initHandlerExceptionResolvers(ApplicationContext context) {
	this.handlerExceptionResolvers = null;

	if (this.detectAllHandlerExceptionResolvers) {
		// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
		Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
				.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
		if (!matchingBeans.isEmpty()) {
			this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values());
			// We keep HandlerExceptionResolvers in sorted order.
			OrderComparator.sort(this.handlerExceptionResolvers);
		}
	}
	else {
		try {
			HandlerExceptionResolver her =
					context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
			this.handlerExceptionResolvers = Collections.singletonList(her);
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Ignore, no HandlerExceptionResolver is fine too.
		}
	}

	// Ensure we have at least some HandlerExceptionResolvers, by registering
	// default HandlerExceptionResolvers if no other resolvers are found.
	if (this.handlerExceptionResolvers == null) {
		this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
		if (logger.isDebugEnabled()) {
			logger.debug("No HandlerExceptionResolvers found in servlet '" + getServletName() + "': using default");
		}
	}
}

以下、備忘録的に補足。

明示的に指定した場合

<bean name="defaultHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver" />

上記の設定だけを行った場合、L6でmatchingBeansが設定され、handlerExceptionResolversが設定されるため、デフォルト値が読み込まれません。

何も設定しなかった場合(デフォルト値)

L27のhandlerExceptionResolversがnullのため、

this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);

で、デフォルトのexceptionResoloverが設定されます。

以上です。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。