Я тем временем осматривался. Я нашел это . В итоге я использовал следующее решение.
Согласно 1 создан ApplicationContextProvider:
public class ApplicationContextProvider implements ApplicationContextAware
{
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext()
{
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
ApplicationContextProvider.applicationContext = applicationContext;
}
}
Затем AppNameProviderFactory, которая сопоставляет провайдеров с ключами. Ключ может быть именем исключения:
public class AppNameProviderFactory
{
private Map<String,AppNameProvider> map;
public void setMap(Map<String, AppNameProvider> map)
{
this.map = map;
}
public AppNameProvider getAppNameProvider(String key)
{
return map.get(key);
}
}
А в xml я определяю сопоставления:
<bean id="appNameProviderFactory" class="some.domain.AppNameProviderFactory">
<property name="map">
<map>
<entry key="MyException" value-ref="appNameProvider"/>
</map>
</property>
</bean>
И, наконец, в классе исключений:
public class MyException extends RuntimeException
{
// Imagine obligatory constructors here...
public String getAppName()
{
final ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
AppNameProviderFactory factory = (AppNameProviderFactory) applicationContext.getBean("appNameProviderFactory");
return factory.getAppNameProvider("MyException").getAppName();
}
}
Таким образом, у меня есть конфигурация в xml, отделенная от бизнес-кода. У меня может быть столько исключений с разными поставщиками, сколько необходимо.
Спасибо всем за предложения.
PS Обработка ошибок и обработка NPE опущены для простоты.