AOP 기반 로그 디 버 깅

정지점 vs 로그
단점 은 우리 가 일상적으로 개발 하 는 가장 흔 하고 효율 적 인 디 버 깅 수단 으로 로그 입력 에 비해 더 많은 상태 정보 와 유연 한 관찰 각 도 를 제공 하지만 단점 디 버 깅 은 전제 와 한계 가 있다.  # 인터페이스 가 우호 적 이 고 기능 이 강 한 IDE 가 필요 합 니 다.  # 단일 기기 의 개발 환경 에서 진행 하기에 비교적 적합 하 다. 기업 응용 개발 에서 우 리 는 단점 디 버 깅 을 할 수 없 는 곤경 에 직면 하 게 된다. 예 를 들 어:  # 이 이상 은 생산 환경 에서 만 나타 나 개발 환경 에서 재현 할 수 없다.  # 외부 시스템 의존, 개발 환경 시 뮬 레이 션 등 이 존재 합 니 다. 이 때문에 우 리 는 * 로그 디 버 깅 * 의 옛길 로 돌아 가 야 합 니 다.
Print vs Logging
간단하게
 
System.out.println("debug infomation");
 
 
너무 간단 하기 때문에 더 많은 정보 (예 를 들 어 스 레 드, 시간 등) 가 필요 하거나 출력 모드 와 형식 을 정의 하려 면 더 많은 코드 를 작성 해 야 하기 때문에 우 리 는 [http://logging.apache.org/log4j Log4j].
왜 AOP 를 기반 으로
Log4j 는 매우 유용 합 니 다. 다만 'System. out. print' 와 마찬가지 로 코드 에서 쉽게 볼 수 있 지만 업무 가치 가 없습니다. 더욱 골 치 아 픈 것 은 매번 우리 가 이런 문 구 를 어디 에 추가 해 야 하 는 지 알려 주 는 충분 한 경험 이 있 는 것 이 아니 라 디 버 깅 에서 코드 에 있 는 위 치 를 바 꾸 기 때문에 반복 적 으로 컴 파일 - 포장 - 발표 시스템 을 컴 파일 하 는 것 입 니 다. 이런 육체 적 인 일 은...너무 예술 적 이지 않 아, 멘 붕!다시 말 하면 우 리 는 희망 할 것 이다.  # Logging 을 업무 에서 분리 하여 코드 를 쉽게 유지 할 수 있 도록 합 니 다.  # 다시 컴 파일 할 필요 가 없고 실행 할 수 있 을 때 출력 로그 의 위 치 를 조정 할 수 있 습 니 다. [http://en.wikipedia.org/wiki/Aspect-oriented_programming AOP] 는 우리 가 상술 한 두 가 지 를 할 수 있 도록 도와 줄 수 있다. 이것 은 전혀 새로운 관점 이 아니다. 이것 은 어떠한 소개 에서 도 [http://en.wikipedia.org/wiki/Aspect-oriented_programming AOP] 글 에서,Logging 은 가장 전형 적 인 응용 장면 이 라 고 언급 하기 때문에 여 기 는 [http://code.google.com/p/google-guice/ Guice], 비 침입 식 을 어떻게 실현 하 는 지, 재 컴 파일 없 이 Logging 위 치 를 바로 잡 을 수 있 는 간단 한 예 를 토론 합 니 다.
 
Guice 기반 예제
나 는 일찍이 [http://log4e.jayefem.de/ Log4E] 의 Eclipse 플러그 인 은 우리 가 미리 설정 한 코드 에 logging 문 구 를 자동 으로 삽입 할 수 있 습 니 다. 예 를 들 어 방법 이 호출 된 수입 과 출구:
public int sum(int a, int b){
    if (logger.isDebugEnabled()){
        logger.debug("sum - start : a is " + a + ", b is " + b);
    }

    int result = a + b;

    if (logger.isDebugEnabled()){
        logger.debug("sum - end : return is " + result);
    }
}

상기 사례 에서 우리 가 디 버 깅 과정 에서 한 가지 방법 으로 들 어가 거나 종료 하 는 상태 (매개 변수, 반환 값 또는 이상) 를 통 해 문제 가 어디 에 있 는 지 분석 할 수 있 습 니 다. 그러면 * MethodInterceptor * 를 통 해 우 리 는 이렇게 할 수 있 습 니 다.
Logging 차단기
 
public class LoggingInterceptor implements MethodInterceptor {


    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        try {
            Object result = invocation.proceed();

            // logging   ,       
            log(invocation.getMethod(), invocation.getArguments(), result);

            return result;
        } catch (Throwable throwable) {

            // logging   ,      
            error(invocation.getMethod(), invocation.getArguments(), throwable);

            throw throwable;
        }
    }
}

 다음은 이 차단 기 를 설정 하고 [http://code.google.com/p/google-guice/ Guice] 성명 하 세 요.
public class LoggingModule extends AbstractModule {

    @Override
    public void configure() {
        bindInterceptor(Matchers.any(), Matchers.any(), new LoggingInterceptor());
    }

}

public class Main {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new BusinessModule(), new LoggingModule());

    }
}

 간단 하지 않 습 니까?이렇게 하면 우리 의 업무 모듈 의 코드 는 출력 로그 의 코드 를 작성 할 필요 가 없습니다. Injector 를 만 들 때 LoggingModule 을 추가 하면 됩 니 다. 등등 로그 출력 위 치 를 설정 하 는 방법 을 잊 어 버 린 것 같 습 니 다. 좋 습 니 다. 이것 은 간단 합 니 다.
로 깅 위치 설정
 
bindInterceptor(Matchers.any(), Matchers.any(), new LoggingInterceptor());

 bindInterceptor 방법의 첫 번 째 매개 변 수 는 차단기 가 모든 클래스 와 일치 하 는 것 을 정의 합 니 다. 두 번 째 매개 변 수 는 차단기 가 하나의 클래스 와 일치 하 는 모든 방법 을 정의 합 니 다. 그러면 우리 가 해 야 할 일 은 외부 매개 변 수 를 통 해 이 두 개의 매개 변 수 를 조정 하면 됩 니 다. 여기 서 정규 표현 식 으로 Logging 과 일치 하 는 방법 을 보 여 줍 니 다.
public class MethodRegexMatcher extends AbstractMatcher<Method> {

    private final Pattern pattern = Pattern.compile(System.getProperty("logging.method.regex", "*"));

    @Override
    public boolean matches(Method method) {
        return pattern.matcher(method.getName()).matches();
    }

}

 안 타 깝 게 도 이런 방법 은 운행 할 때 조정 할 수 없 지만, 이것 도 실현 할 수 있다.
실행 중 로 깅 위치 설정
아니면 Logging 할 정규 표현 식 과 일치 하 는 방법 을 예 로 들 면:
public class LoggingInterceptor implements MethodInterceptor {

    private String regex = "*";

    public void setMethodRegex(String regex){
        this.regex = regex;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        String methodName = invocation.getMethod().getName();

        try {
            Object result = invocation.proceed();

            if (methodName.matches(regex))
                // logging   ,       
                log(invocation.getMethod(), invocation.getArguments(), result);

            return result;
        } catch (Throwable throwable) {

            if (methodName.matches(regex))
                // logging   ,      
                error(invocation.getMethod(), invocation.getArguments(), throwable);

            throw throwable;
        }
    }
}

 그 다음 에 JMX 동적 으로 regex 의 값 을 조정 하여 실행 할 때의 설정 을 실현 할 수 있 습 니 다. 물론 더 좋 은 방법 이 있 을 것 입 니 다. 알 고 있다 면 공유 해 보 세 요.
 
작은 매듭
본 고 는 Guice 를 예 로 들 어 우리 의 일상적인 개발 에서 디 버 깅 문 제 를 어떻게 개선 하 는 지 토론 하고 자 한다. 사실은 이것 은 Spring 응용 에서 도 똑 같이 실현 할 수 있 고 심지어 다른 AOP 를 응용 하 는 장면 도 모두 가능 하 다. 확대 하면 Logging 뿐만 아니 라 검증 (테스트) 도 가능 하 다 고 할 수 없다.이렇게 말 하지 않 았 습 니까? "생각 이 얼마나 멀 면 우 리 는 얼마나 멀리 갈 수 있 습 니까?"
 

좋은 웹페이지 즐겨찾기