LostCatBox

스프링 핵심 원리 고급편(AOP 포함)(작성중)

Word count: 534Reading time: 3 min
2024/01/09 Share

왜?

  • AOP 등등 다양한 기술을 spring 에 접목하기위함
  • 크게 5가지 기술과 디자인 패턴한다.
    • 쓰레드 로컬
    • 패턴들(템플릿 메서드 패턴, 콜백 패턴, 프록시 패턴, 데코레이터 패턴)
    • 동적 프록시 기술
    • 빈 후처리
    • AOP

로그추적기

V0 (가장 단순한 구조) C-S-R

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequiredArgsConstructor
public class OrderControllerV0 {

private final OrderServiceV0 orderService;

@GetMapping("/v0/request")
public String request(String itemId) {
orderService.orderItem(itemId);
return "ok";
}
}
1
2
3
4
5
6
7
8
9
10
@Service
@RequiredArgsConstructor
public class OrderServiceV0 {

private final OrderRepositoryV0 orderRepository;

public void orderItem(String itemId) {
orderRepository.save(itemId);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Repository
@RequiredArgsConstructor
public class OrderRepositoryV0 {

public void save(String itemId) {
//저장 로직
if (itemId.equals("ex")) {
throw new IllegalStateException("예외 발생!");
}
sleep(1000);
}

private void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

로그 추적기 V1

  • traceId
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package hello.advanced.trace;

import java.util.UUID;

public class TraceId {

private String id;
private int level;

public TraceId() {
this.id = createId();
this.level = 0;
}

private TraceId(String id, int level) {
this.id = id;
this.level = level;
}

private String createId() {
return UUID.randomUUID().toString().substring(0, 8);
}

public TraceId createNextId() {
return new TraceId(id, level + 1);
}

public TraceId createPreviousId() {
return new TraceId(id, level - 1);
}

public boolean isFirstLevel() {
return level == 0;
}

public String getId() {
return id;
}

public int getLevel() {
return level;
}
}
  • traceStatus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package hello.advanced.trace;

public class TraceStatus {

private TraceId traceId;
private Long startTimeMs;
private String message;

public TraceStatus(TraceId traceId, Long startTimeMs, String message) {
this.traceId = traceId;
this.startTimeMs = startTimeMs;
this.message = message;
}

public TraceId getTraceId() {
return traceId;
}

public Long getStartTimeMs() {
return startTimeMs;
}

public String getMessage() {
return message;
}
}
  • helloTraceV1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Slf4j
@Component
public class HelloTraceV1 {

private static final String START_PREFIX = "-->";
private static final String COMPLETE_PREFIX = "<--";
private static final String EX_PREFIX = "<X-";

public TraceStatus begin(String message) {
TraceId traceId = new TraceId();
Long startTimeMs = System.currentTimeMillis();
log.info("[{}] {}{}", traceId.getId(), addSpace(START_PREFIX, traceId.getLevel()), message);
return new TraceStatus(traceId, startTimeMs, message);
}

public void end(TraceStatus status) {
complete(status, null);
}

public void exception(TraceStatus status, Exception e) {
complete(status, e);
}

private void complete(TraceStatus status, Exception e) {
Long stopTimeMs = System.currentTimeMillis();
long resultTimeMs = stopTimeMs - status.getStartTimeMs();
TraceId traceId = status.getTraceId();
if (e == null) {
log.info("[{}] {}{} time={}ms", traceId.getId(), addSpace(COMPLETE_PREFIX, traceId.getLevel()), status.getMessage(), resultTimeMs);
} else {
log.info("[{}] {}{} time={}ms ex={}", traceId.getId(), addSpace(EX_PREFIX, traceId.getLevel()), status.getMessage(), resultTimeMs, e.toString());
}
}

private static String addSpace(String prefix, int level) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < level; i++) {
sb.append((i == level - 1) ? "|" + prefix : "| ");
}
return sb.toString();
}

}
  • HelloTraceV1Test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class HelloTraceV1Test {

@Test
void begin_end() {
HelloTraceV1 trace = new HelloTraceV1();
TraceStatus status = trace.begin("hello");
trace.end(status);
}

@Test
void begin_exception() {
HelloTraceV1 trace = new HelloTraceV1();
TraceStatus status = trace.begin("hello");
trace.exception(status, new IllegalStateException());
}
}
CATALOG
  1. 1. 왜?
  2. 2. 로그추적기
  3. 3. V0 (가장 단순한 구조) C-S-R
  4. 4. 로그 추적기 V1