[java] 로거는 비공개 정적이어야하는지 여부

로거를 정적으로 선언해야합니까? 일반적으로 로거에 대한 두 가지 유형의 선언을 보았습니다.

    보호 된 로그 로그 = new Log4JLogger (aClass.class);

또는

    개인 정적 로그 로그 = new Log4JLogger (aClass.class);

어느 것을 사용해야합니까? 둘 다의 장단점은 무엇입니까?



답변

비 정적 형식의 장점은 올바른 클래스 이름이 사용된다는 걱정없이 다음과 같이 (추상) 기본 클래스에서 선언 할 수 있다는 것입니다.

protected Log log = new Log4JLogger(getClass());

그러나 단점은 클래스의 모든 인스턴스에 대해 완전히 새로운 로거 인스턴스가 생성된다는 것입니다. 이것은 그 자체로 비싸지는 않지만 상당한 오버 헤드를 추가합니다. 이것을 피하려면 static대신 양식 을 사용하는 것이 좋습니다. 그러나 단점은 차례로 모든 개별 클래스에서 선언해야하고 로거 생성 중에 올바른 클래스 이름이 사용 된 모든 클래스에서주의를 기울여야한다는 것입니다.getClass() 하고 정적 컨텍스트에서 사용할 수 입니다. 그러나 평균 IDE에서는 이에 대한 자동 완성 템플릿을 만들 수 있습니다. 예 : logger+ ctrl+space.

반면에 이미 인스턴스화 된 로거를 캐시 할 수있는 공장에서 로거를 얻는 경우, 비 정적 형식을 사용하면 그다지 많은 오버 헤드가 추가되지 않습니다. 예를 들어 Log4j는 LogManager이러한 목적을 위해 있습니다.

protected Log log = LogManager.getLogger(getClass());


답변

나는 모든 로거가 정적이어야한다고 생각했습니다. 그러나 wiki.apache.org의이 기사 클래스 로더 누출과 관련하여 몇 가지 중요한 메모리 문제를 제기합니다. 로거를 정적으로 선언하면 선언 클래스 (및 관련 클래스 로더)가 공유 클래스 로더를 사용하는 J2EE 컨테이너에서 가비지 수집되는 것을 방지합니다. 애플리케이션을 충분히 재배포하면 PermGen 오류가 발생합니다.

로거를 비 정적으로 선언하는 것 외에는이 클래스 로더 누수 문제를 해결할 수있는 방법이 없습니다.


답변

가장 중요한 차이점은 로그 파일에 미치는 영향입니다. 로그는 어떤 범주로 이동합니까?

  • 첫 번째 선택에서 하위 클래스의 로그는 수퍼 클래스의 범주에 속합니다. 그것은 나에게 매우 반 직관적 인 것 같습니다.
  • 첫 번째 경우의 변형이 있습니다.

    보호 된 로그 로그 = new Log4JLogger (getClass ());

    이 경우 로그 카테고리는 로그 된 코드가 어떤 개체에서 작동하고 있는지 알려줍니다.

  • 두 번째 선택 (개인용 정적)에서 로그 범주는 로깅 코드를 포함하는 클래스입니다. 따라서 일반적으로 기록되는 작업을 수행하는 클래스입니다.

마지막 옵션을 강력히 권장합니다. 다른 솔루션에 비해 다음과 같은 장점이 있습니다.

  • 로그와 코드 사이에는 직접적인 관계가 있습니다. 로그 메시지의 출처를 쉽게 찾을 수 있습니다.
  • 누군가가 로깅 수준 (범주별로 수행됨)을 조정해야하는 경우 일반적으로 특정 클래스에서 작성한 특정 메시지에 관심이 있거나 그렇지 않기 때문입니다. 카테고리가 메시지를 작성하는 클래스가 아닌 경우 레벨을 조정하기가 더 어렵습니다.
  • 정적 메소드에 로그인 할 수 있습니다.
  • 로거는 생성 된 모든 인스턴스가 아닌 시작시 클래스 당 한 번만 초기화 (또는 조회)하면됩니다.

또한 단점이 있습니다.

  • 메시지를 기록하는 모든 클래스에서 선언해야합니다 (슈퍼 클래스 로거 재사용 없음).
  • 로거를 초기화 할 때 올바른 클래스 이름을 입력하도록주의해야합니다. (하지만 좋은 IDE가 알아서 처리합니다).

답변

제어 반전을 사용하고 로거를 생성자에 전달하십시오. 클래스 내부에 로거를 만들면 단위 테스트로 시간을 낭비하게 될 것입니다. 당신은 단위 테스트를 작성하고 있습니까?


답변