2011-11-24 5 views
4

나는 비슷한 질문을 Spring - how to inject a bean into class which is created many times at runtime?Why is Spring's ApplicationContext.getBean considered bad?으로 발견했다.Spring bean을 Exception에 삽입하는 방법

예제 코드 :

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에 선언 공급자 콩 있습니다. 이 예제에서 값은 단순화를 위해 xml로 간단히 선언됩니다. 나는 bean으로부터 무언가를받을 필요가있는 custom exception을 가지고있다. 그런 빈을 예외 클래스에 주입하는 방법. 분명히 Spring 빈처럼 예외를 선언 할 수는 없습니다. appName은 단순한 예일 뿐이고 다른 어떤 것도 될 수 있습니다. myException.getAppName()의 hypothetic 호출자가 appNameProvider.getAppName()을 호출하지 않는 이유가 궁금 할 것입니다. 의도적이지 않으므로 각 예외 등에서 다른 공급자가있을 수 있습니다.

나는 이러한 예외에 빈을 삽입하는 방법을 알고 싶습니다. setter를 추가하고 예외 발생 시간에 공급자를 설정할 수 있습니다. 하지만 (내 응용 프로그램 코드에서) 외부에서 사용할 공급자를 알고 있어야하며이 예외를 throw하려는 모든 곳에서 중복으로 처리해야합니다. 이상적으로 XML에서 예외에 사용할 공급자를 선언하고 싶습니다.

궁극적으로 질문은 예외가 아닌 bean 자체가 아닌 런타임 객체를 생각할 수 있도록 확장 될 수 있습니다.

추신 : 나는 코드에서 Spring에 대한 하드 코드 된 의존성을 갖는 것을 두려워하지 않습니다. 나는 봄을 사용하고 그것을 포옹하고 싶다 - 그것을 피하지 말라. 나는했습니다 이후

+0

'MyException'의 새 인스턴스를 throw하는 코드를 게시 할 수 있습니까? 나는 당신이 생성자를 통해 AppNameProvider에 대한 참조를 전달할 수 없다면 궁금하다 ... – JBert

답변

1
  1. 예외로 공급자를 설정하는 기준에 생성자/세터를 제공 제외
  2. 을 던지는 클래스의 프로 바이더를 주사는
  3. throw new MyException(provider)
+0

Bozho 및 JBert에 대한 답변 : 예외를 throw하는 시간에 setter를 추가하고 공급자를 설정할 수 있습니다. 하지만 (내 응용 프로그램 코드에서) 외부에서 사용할 공급자를 알고 있어야하며이 예외를 throw하려는 모든 곳에서 중복으로 처리해야합니다. – user1063845

+0

@ user1063845 문제는, 당신이 예외를 던질 어떤 문맥에서 그리고 당신이 그것을 잡는 곳에서 실제로 AppnameProvider가 필요한지를 알고 싶습니다. 나는 당신이 예외를 던질 때 누군가가 AppnameProvider를 구현하는 클래스에서 잘못된 연산을 수행했다는 것을 알았습니다. 이것은 당신이 공급자의 인스턴스를 가져 왔음을 의미합니다. 나는 Spring이 마술 트릭을 할 수 있다고 확신하지만, 디자인에 결함을 수정하려고하는 것처럼 들린다. 이 작업을 수행하는 데 필요한 봄 마법은 나중에 코드에서 작업하는 모든 사람들이 이해할 수없는 코드가 될 수 있습니다. – JBert

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

저는 주변을 둘러 보았습니다. 나는 this을 발견했다. 결국 나는 다음과 같은 해결책을 사용했다.

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 : 1에 따르면

는 ApplicationContextProvider를 만들었습니다.열쇠가 될 수있는 예외 이름 :

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

그리고 마지막으로 예외 클래스 :

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에

나는 매핑을 정의

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 처리.

관련 문제