Java에서 로거를 선언하는 것이 가장 좋은 방법은 static final
무엇입니까?
private static final Logger S_LOGGER
Java에서 로거를 선언하는 것이 가장 좋은 방법은 static final
무엇입니까?
private static final Logger S_LOGGER
답변:
private
-다른 클래스가 귀하의 로거를 납치 할 수 없도록static
-클래스 당 하나의 로거 인스턴스 만 있으므로 로거를 직렬화하려는 시도를 피할 수 있습니다.final
-수업 기간 동안 로거를 변경할 필요가 없습니다.또한 log
가능한 한 단순하면서도 설명적인 이름 을 선호합니다 .
편집 : 그러나이 규칙에는 흥미로운 예외가 있습니다.
protected final Logger log = LoggerFactory.getLogger(getClass());
반대로 :
private static final Logger log = LoggerFactory.getLogger(Foo.class);
전자를 사용하면 상속 계층 전체의 모든 클래스에서 동일한 로거 이름 (실제 클래스의 이름)을 사용할 수 있습니다. 따라서 Bar
확장 Foo
하면 Bar
로거에 모두 기록됩니다 . 더 직관적 인 사람들도 있습니다.
log
코드를 산란하는 것보다 작성하기 쉽고 이름 을 읽는 것이 더 좋습니다 LOG
. 개발자의 문제. 팀 계약.
이 블로그 게시물 : Java 정적 로거 제거를 확인하십시오 . 이것은 jcabi-log 와 함께 slf4j 를 사용하는 방법입니다 .
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
정적 잡음을 더 이상 사용하지 마십시오.
static
즉, 클래스 인스턴스 당 하나의 로거가 아니라 클래스 당 하나의 로거 만 작성 합니다. 로거는 클래스에 따라 달라지기 때문에 일반적으로 원하는 것입니다.
final
logger
변수 의 값을 변경하지 않을 것임을 의미 합니다. 거의 항상 모든 로그 메시지를 (한 클래스에서) 동일한 로거로 던지기 때문입니다. 드문 경우이지만 클래스가 일부 메시지를 다른 로거에 보내려고 할 때도 widgetDetailLogger
정적 변수의 값을 즉시 변경하지 않고 다른 로거 변수 (예 :)를 작성하는 것이 훨씬 더 명확합니다 .
일반적으로 클래스 이름을 사용하여 기록하도록 로거를 초기화합니다. 즉, 정적이 아닌 경우 클래스의 인스턴스가 많은 각 인스턴스 (메모리 공간 부족)가 발생하지만이 로거는 모두 동일한 구성을 공유하고 정확히 동일하게 작동합니다. 그것이 static
비트 뒤에있는 이유 입니다. 또한 각각 Logger
클래스 이름으로 초기화 되므로 하위 클래스와의 충돌을 막기 위해 private
상속 할 수 없도록 선언합니다 . 은 final
당신이 일반적으로 변경하지 않는 것이 포인트에서 유래 Logger
하여 (이 경우는 아무도 그것을 변경할 수 있도록하는 것을 최종 확인하는 것이 합리적이다 - 그래서 한 번 당신이 "다시는 구성하지"결코하여 초기화 - 실행 중 실수 또는 그렇지 않으면). 물론 당신이 사용하려는 경우Logger
다른 방법 으로 사용 하지 않아도 될 수도 static final
있지만 앱의 80 %가 위에서 설명한대로 로깅을 사용한다고 생각합니다.
이 질문에 대답하려면 "정적"과 "최종"이 무엇인지 스스로에게 물어야합니다.
Logger의 경우 (Log4J Logger 클래스에 대해 이야기한다고 가정) 클래스별로 범주를 원합니다. 이것은 한 번만 할당하고 클래스 당 하나 이상의 인스턴스가 필요하지 않다는 사실로 이어질 것입니다. 아마도 한 클래스의 Logger 객체를 다른 클래스에 노출시킬 이유가 없기 때문에 비공개로 만들고 일부 OO 원칙을 따르지 않는 이유는 무엇입니까?
또한 컴파일러는 그 이점을 활용할 수 있습니다. 따라서 코드가 약간 더 잘 수행됩니다. :)
이는 일반적으로 객체의 모든 인스턴스에서 공유 할 수있는 기능의 종류이기 때문입니다. 같은 클래스의 두 인스턴스에 대해 서로 다른 로거를 갖는 것은 의미가 없습니다 (90 %의 시간).
그러나 때때로 로거 클래스가 싱글 톤으로 선언되거나 단순히 정적 함수를 제공하여 물건을 기록하는 것을 볼 수도 있습니다.
이 코드는 취약하지만 Java7 이후 Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
에는 정적 로거 대신 사용할 수 있습니다 .
This is code is vulnerable
당신은 조금 대답을 명확히 할 수 있습니까?
이상적으로 Logger는 Sonar를 제공하지 않고 호환 코드를 제공하기 위해 Java 7까지 다음과 같아야합니다. private : 부모 클래스 외부에서는 액세스 할 수 없습니다. 다른 클래스가 무언가를 기록해야하는 경우 자체 로거를 인스턴스화해야합니다. static : 클래스의 인스턴스 (객체)에 의존하지 않습니다. 무엇인가를 로깅 할 때, 물론 상황 정보가 메시지에 제공 될 수 있지만 각 객체와 함께 로거가 생성되지 않도록하여 메모리 사용량이 많지 않도록 로거를 클래스 레벨에서 작성해야합니다. final : 수업 당 한 번만 작성하십시오.
다른 답변에 주어진 이유 외에도 내가 겪었던 한 가지 이유는 내 로거가 정적이거나 최종적이지 않은 것입니다.
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
어떤 경우에는 (Gson 라이브러리를 사용했을 때) stackoverflow 예외가 발생합니다. 내 구체적인 상황은 비 정적 최종 로거가 포함 된 클래스를 인스턴스화하는 것이 었습니다. 그런 다음 GsonBuilder를 호출 한 toJson 메소드를 호출하십시오.
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
실제로 정적 로거는 정적 컨텍스트에서 작동해야하므로 "유해"할 수 있습니다. 동적 환경이있는 경우 예. OSGi는 비 정적 로거를 사용하는 데 도움이 될 수 있습니다. 일부 로깅 구현은 내부적으로 로거 캐싱 (AFAIK 이상 log4j)을 수행하므로 성능 영향은 무시할 수 있습니다.
정적 로거의 한 가지 단점은 다음과 같습니다. 가비지 수집 (클래스가 한 번만 사용되는 경우 (예 : 초기화 중 로거는 계속 유지됨))
자세한 내용은 다음을 확인하십시오.
또한보십시오:
인터넷에서 로거를 정적으로 만드는지에 관한 정보에 따르면, 가장 좋은 방법은 사용 사례에 따라 사용하는 것입니다.
두 가지 주요 주장이 있습니다.
1) 정적 상태로 만들면 가비지 수집되지 않습니다 (메모리 사용 및 성능).
2) 정적이 아닌 경우 각 클래스 인스턴스에 대해 생성됩니다 (메모리 사용량)
따라서 싱글 톤에 대한 로거를 작성할 때 정적 로거로 만들 필요가 없습니다. 하나의 인스턴스 만 있으므로 로거는 하나만 있기 때문입니다.
반면에 모델 또는 엔티티 클래스에 대한 로거를 작성하는 경우 중복 된 로거를 작성하지 않도록 정적으로 만들어야합니다.