2017-01-21 11 views
0

열거 형에 내 로거 생성기를 삽입하려고하면 NPE가 발생합니다. 열거 형에 Logger를 주입하려면 어떻게해야합니까?열거 형에 로거를 주입하는 방법

public enum MyEnum { 

    HI("Hi there!"), 
    HELLO("Hello mister!"); 

    @Inject 
    private Logger log; 

    private final String greeting; 

    private MyEnum(String greeting) { 
     this.greeting = greeting; 
//  this.log = LoggerFactory.getLogger(this.getClass()); 
    } 

    public String getGreeting() { 
     log.debug("Method getGreeting called"); 
     return this.greeting; 
    } 

} 

이 클래스는 나에게 log.debug() 줄에 NPE을 제공 : 예

. @Inject을 제거하고 this.log 행의 주석 처리를 제거하면 작동합니다.

테스트 케이스는 다음과 같습니다

이 질문에 대한
@RunWith(Arquillian.class) 
public class CoverKindTest { 

    @Deployment 
    public static WebArchive createDeployment() { 
     return ShrinkWrap.create(WebArchive.class, "test.war") 
       .addClass(MyEnum.class) 
       .addClass(LoggerProducer.class) 
       .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); 
    } 

    @Test 
    public void testEnum() { 
     MyEnum myEnum = MyEnum.HI; 
     String greeting = myEnum.getGreeting(); 
     assertThat("Should give the greeting.", greeting, is("Hi there!")); 
    } 

} 

완전한 검증이 프로젝트는 MyEnum.class가 원래의 질문이다, 여기에서 찾을 수 있습니다, MyEnum1.class 주입없이 솔루션입니다 (작업,하지만 내가 찾고 있어요되지 것) 그리고 MyEnum2.class이 좋습니다.

편집 : 작동하는 솔루션으로 GitHub 레포를 업데이트했습니다. https://github.com/martijnburger/how-to-inject-a-logger-in-an-enum

+1

나는 이유는 당신이 로거하고 주입 CDI를 사용하여 생각 열거 형이 빈이 아니기 때문에 작동하지 않습니다. => 로거가 null로 유지됩니다. –

+1

열거 형은 어떻게 부릅니까? Inject가 사용되는 클래스가 프록시 생성 객체 여야하는 클래스를 작동시키기 위해서. 나는 당신이 직접'MyEnum.HI.getGreeting()'을 호출하고있는 것으로 추측하고 있는데, 해당 DI 프레임 워크는 어떤 변수를 주입해야한다는 것을 모를 것이다. 이 코드를 어떻게 호출했는지 코드를 붙여 넣을 수 있습니까? –

+0

@BandiKishore 네, 그게 제가 사용하는 방법입니다. 나는 테스트 케이스를 추가했다. 이 상황에서 로깅을 위해'LoggerProducer'를 사용할 방법이 있습니까? –

답변

1

해결책을 찾았습니다!

public class LoggerHelper { 

    private static Logger logger; 

    private void injectLogger(@Observes @Initialized(ApplicationScoped.class) Object context, 
      Logger logger) { 
     LoggerHelper.logger = logger; 
    } 

    public static Logger getLogger() { 
     return logger; 
    } 

} 

은 지금은 사용하여 열거에서 로거를 삽입 할 수 있습니다 다음과 같이

나는 도우미 클래스를 만들었

private final Logger log = LoggerHelper.getLogger(); 
2

enum이 정적이므로이 직접 주입이 작동하지 않습니다. 은 정전기있는 한 당신은, 주입 할 수없는 당신의 열거 클래스

private static final Logger log = Logger.getLogger(Myenum.class.getName()); 
+0

예. 나는 그것을 이해하고 그것이 효과가 있다는 것을 안다. 그러나 문제는 열거 형에 로그인하기 위해 CDI 주입을 사용자에게 적용하는 방법입니다. –

+0

enum 클래스에 내부 클래스 LogInjector를 만들고 내부 클래스에 해당 로거를 삽입 할 수 있습니다. – shubham

+0

예를 들어 주시겠습니까? –

0

열거 형에 새로운 로거를 만들 수 있습니다.

주입 (Logger를 만드는 대신)을 계속하려면 setum 또는 생성자 주입이있는 정적 클래스를 열거 형 내에 만들어야합니다. setter 나 생성자가 DI 프레임 워크에 의해 호출되면, 당신에게 주어진 값을 받아 열거 형의 정적 값에 할당하십시오.

열거 형은 필요에 따라 지금 액세스 할 수 있습니다. 클래스가 아직 주입되지 않았다면 값은 null이됩니다. 이 같은

뭔가 : - (봄 말하여 각각의 DI 프레임 워크에 의해 생성) 클래스 내에서이 로그를 주입하고 열거에서 사용

public enum MyEnum { 

     HI("Hi there!"), 
     HELLO("Hello mister!"); 

     private static Logger log; 

     private final String greeting; 

     private MyEnum(String greeting) { 
      this.greeting = greeting; 
     } 

     public String getGreeting() { 
      log.debug("Method getGreeting called"); 
      return this.greeting; 
     } 

     @Component 
     public static class InjectionHelper { 
     @Inject 
     public InjectionHelper(Logger log) { 
      MyEnum.log = log; 
     } 
     } 
    } 
+0

감사합니다. 나는 아직도 NPE를 얻는다. 내 업데이트 된 질문을보십시오.뭐가 문제 야? "수업이 아직 주사되지 않았다면"은 무엇을 의미합니까? –

+0

당신은 내가 한 말을하지 않았습니다. – john16384

+0

로거를 위해이 작업을 수행하지는 않겠지 만 ... 귀하의 코드입니다. – john16384

-1

당신은 싱글 서비스 클래스를 만들 수 있습니다.

다음은 작동하는 샘플 코드입니다. (당신이 그 일의 XML 방식을 사용하는 경우, XML에서이 클래스의 빈 태그 서비스 주석을 교체합니다. 또한이 롬복 @Getter 주석을 무시하고 정적 게터로 교체 할 수 있습니다) 이제

// Service which is actually a Utility class but have DI Managed Beans. 
@Service("staticService") 
public class StaticService { 

    @Getter 
    private static Logger log; 

    @Inject 
    StaticService(Logger log) { 
     StaticService.log = log; 
    } 
} 

해당 열거 형에서 :

나는 내 수업 (In Spring) 중 하나에 대해 비슷한 패턴을 사용하고 주입이 효과적이었습니다.

논리 : 우리는 먼저 클래스 (싱글 톤 인스턴스)의 인스턴스를 만들고 생성자에서 필요한 변수를 주입

  1. .
  2. 스프링 초기화 (응용 프로그램 시작 도중)가 호출되기 때문에 로그가 초기화되고 수동으로 생성자에 삽입 된 객체의 정적 변수를 지정합니다.

참고 :

  1. 생성자 인수의를 주입 주석을 잊지 마십시오.
  2. 이 로그 개체에 setter 메서드를 제공하지 않는 것이 좋습니다. 그것의 정적 인 것과 공유 된 것, 우리는 사람들이 건설 후이 가치를 대체하기를 원하지 않습니다. (최종적으로 만드는 것은 정적 인 것처럼 옵션이 아닙니다.)
+0

봄이 아니라 CDI를 사용하고 있습니다. 그러나 나는 네가하는 말을 이해하고 그것을 시도했다. 그것은 여전히 ​​나에게 getLog() 메소드에 대한 NPE를 제공합니다. –

+0

이상 하네. CDI가 Logger 객체를 알고 있으면이 메서드가 작동합니다. 다른 클래스 레벨 주입과 유사합니다. CDI에 대해서는 잘 모르겠지만 StService 클래스에 대한 Bean 인스턴스를 작성하기 위해 @Service 또는 XML 항목과 같은 주석이있을 수 있습니까? 어쩌면 당신이 그것을 추가하고 볼 수 있습니다. –

+0

https://docs.oracle.com/javaee/7/api/javax/ejb/Singleton.html –