我在Spring - how to inject a bean into class which is created many times at runtime?和Why is Spring's ApplicationContext.getBean considered bad?找到了类似的问题但是我的情况并没有真正回答。
示例代码:
public interface AppNameProvider
{
String getAppName();
}
public class DefaultAppNameProvider implements AppNameProvider
{
private String appName;
public String getAppName()
{
return appName;
}
public setAppName(String appName)
{
this.appName = appName;
}
}
<bean id="appNameProvider" class="some.package.DefaultAppNameProvider">
<property name="appName" value="MyApplication"/>
</bean>
public class MyException extends RuntimeException
{
// Imagine obligatory constructors here...
public String getAppName()
{
// Inject appNameProvider somehow here
return appNameProvider.getAppName();
}
}
我有一个在xml中声明的提供者bean。在示例中,为简单起见,该值仅在xml中声明。我有一个自定义异常,需要从bean接收一些东西。如何将这样的bean注入异常类。我显然不能将异常声明为Spring bean。 appName只是一个简单的例子,它可以是其他任何东西。您可能想知道为什么myException.getAppName()的假设调用者不只是简单地调用appNameProvider.getAppName()?因为它不是这样的,例如,每个例外都可能有不同的提供者等。
我想知道如何将bean注入此类异常。我可以添加setter并在异常抛出时设置提供程序。但我必须知道从外部使用哪个提供程序(在我的应用程序代码中),我将不得不在我想要抛出此异常的任何地方冗余地执行此操作。理想情况下,我想在xml中声明要用于异常的提供程序。
最终问题可以扩大,以便我们不考虑异常,而是考虑任何不是bean本身的运行时对象。
PS我并不害怕在代码中对Spring进行硬编码依赖。我使用Spring,我想拥抱它 - 不要避免它。
答案 0 :(得分:1)
throw new MyException(provider)
答案 1 :(得分:0)
我已经有一段时间了,但如果您正在使用/可以使用基于注释的配置和aspectJ,您可以将类注释为@Configurable
,这将允许您在每次实例时让Spring注入依赖项该类的创建。
答案 2 :(得分:0)
您可以创建一个组件并在其中注入属性。例如,您可以将DefaultAppNameProvider
定义为组件,因此您可以在其中自动装配其他组件。然后,您可以使用单一设计模式和私有构造函数提供一个名为getInstance的静态方法。在类MyException
中,您可以使用DefaultAppNameProvider.getInstance().getAppName()
访问DefaultAppNameProvider属性。
单例组件的示例代码。
@Component
public class DefaultAppNameProvider {
private static DefaultAppNameProvider instance;
private DefaultAppNameProvider() {
instance = this;
}
public static DefaultAppNameProvider getInstance() {
return instance;
}
private String appName;
public String getAppName()
{
return appName;
}
public setAppName(String appName)
{
this.appName = appName;
}
}
答案 3 :(得分:0)
我一直在环顾四周。我找到了this。最后我使用了以下解决方案。
根据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处理因为简单而无法理解。