How to insert Spring bean in exception

I found a similar question here in Spring - how to insert a bean class into a class that is created many times at runtime? and Why is the Spring ApplicationContext.getBean application considered bad? but really doesn't answer my question.

Code example:

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(); } } 

I have a bean provider declared in xml. In the example, the value is simply declared in xml for simplicity. I have the usual exception to get from a bean. How to introduce such a bean to an exception class. I obviously cannot declare an exception as a Spring bean. AppName is just a simple example, it can be anything. You might be wondering why the hypothetical caller myException.getAppName () will not just just call appNameProvider.getAppName ()? Because it is not intended for this, for example. each exception may have a different provider.

I would like to know how to introduce a bean to such an exception. I can add a setter and set the provider during the time the exception is thrown. But I need to know which provider to use externally (in my application code), and I will have to do it redundantly wherever I want to throw this exception. Ideally, I would like to declare which provider to use for exception in xml.

Ultimately, the question can be expanded, so instead of throwing an exception, we think of some runtime object that is not the bean itself.

PS I'm not afraid of having hard-coded Spring dependencies in the code. I am using Spring and I want to cover it - do not avoid this.

+4
source share
4 answers
  • Introduce the provider into the class that throws the exception
  • Provide a constructor / setter with which you can set the provider to an exception
  • throw new MyException(provider)
+1
source

This is since I did this, but if you use / can use annotation and aspectJ based configuration, you can annotate the class as @Configurable , which will allow you to get Spring to add dependencies every time an instance of the class.

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-atconfigurable

0
source

You can create a component and enter a property in it. For example, you can define DefaultAppNameProvider as a component, and thus you can use other components in it. Then you can use the singleton design pattern with a private constructor, the static getInstance method. In the MyException class MyException you can access the DefaultAppNameProvider property with DefaultAppNameProvider.getInstance().getAppName() .

Sample code for a singleton component.

 @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; } } 
0
source

I surveyed this time. I found this one . In the end, I used the following solution.

According to 1 created by 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; } } 

Then AppNameProviderFactory, which maps providers to keys. The key may be the name of the exception:

 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); } } 

And in xml, I define the mappings:

 <bean id="appNameProviderFactory" class="some.domain.AppNameProviderFactory"> <property name="map"> <map> <entry key="MyException" value-ref="appNameProvider"/> </map> </property> </bean> 

And finally, in the exception class:

 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(); } } 

This way I have a configuration in xml, detachable from the business code. If necessary, I can have as many exceptions as possible with different providers.

Thanks everyone for the suggestions. PS Error handling and NPE processing are simplified.

0
source

Source: https://habr.com/ru/post/1382895/


All Articles