원래 객체의 기능을 다른 객체가 대신 처리하도록 설계하는 패턴
AOP 등에 사용되는 패턴
Proxy 기본 패턴
[Subject interface]
1
2
3
|
public interface Subject {
public String action();
}
|
cs |
[RealSubject class]
실제 사용하는 객체
1
2
3
4
5
6
7
8
|
public class RealSubject implements Subject{
@Override
public String action() {
return "Real Subject action()";
}
}
|
cs |
[Proxy class]
프록시 객체.
내부적으로 RealSubject 객체를 생성하여 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Proxy implements Subject {
RealSubject realSubject;
@Override
public String action() {
if(realSubject == null) {
realSubject = new RealSubject();
}
return realSubject.action();
}
}
|
cs |
[Client class]
1
2
3
4
5
6
7
8
9
|
public class Client {
public static void main(String[] args) {
Subject subject = new Proxy();
System.out.println(subject.action());
}
}
|
cs |
Proxy의 실제 사용
[AOP 흉내내기]
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
|
public class Proxy implements Subject {
RealSubject realSubject;
@Override
public Object action() {
if(realSubject == null) {
realSubject = new RealSubject();
}
preProcess();
Object result = realSubject.action();
postProcess();
return result;
}
private void preProcess() {
System.out.println("선행작업");
}
private void postProcess() {
System.out.println("사후작업");
}
}
|
cs |
[실제 AOP 소스]
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
@Component
@Aspect
public class ControllerAOP {
protected static final Logger logger = LoggerFactory.getLogger(ControllerAOP.class);
private final String CANNOT_PRINT_INPARAM = "{IN_PARAMS LENGTH IS TOO LONG TO PRINT}";
private final String CANNOT_PRINT_OUTPARAM = "{OUT_PARAMS LENGTH IS TOO LONG TO PRINT}";
private final String CANNOT_PRINT_VALUE = "VALUE LENGTH IS TOO LONG TO PRINT";
private final String NOTHING_TO_PRINT = "RETURN TYPE IS VOID";
@Around("execution(public void com.sample..*Controller.*(..))")
public void voidAround(ProceedingJoinPoint pjp) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String inputParam = null;
for (Object obj : pjp.getArgs()) {
if (obj instanceof Map) {
inputParam = obj.toString();
} else if (obj instanceof String){
inputParam = (String)obj;
}
}
long start = System.currentTimeMillis();
String controller = (String) pjp.getTarget().getClass().getSimpleName();
String path = request.getRequestURI();
String addr = request.getRemoteAddr();
int port = request.getRemotePort();
logger.info("##########################################################################");
logger.info("# REQUEST | CONTROLLER = {} | METHOD = {} | REMOTEADDR = {} | PORT = {} | IN_PARAMS = {}",
controller, path, addr, port, inputParam==null?"":(inputParam.length()>=1500?this.CANNOT_PRINT_INPARAM:inputParam));
logger.info("##########################################################################");
String result_msg = "success";
try {
pjp.proceed();
result_msg = "success";
} catch (APIException e) {
result_msg = "fail";
} catch (Throwable e) {
result_msg = "fail";
} finally {
long end = System.currentTimeMillis();
logger.info("##########################################################################");
logger.info("# RESPONSE | CONTROLLER = {} | METHOD = {} | RESULT = {} | REMOTEADDR = {} | PORT = {} | TIME = {} ms | IN_PARAMS = {} | OUT_PARAMS = {}",
controller, path, result_msg, addr, port, end-start, inputParam==null?"":(inputParam.length()>=1500?this.CANNOT_PRINT_INPARAM:inputParam),
this.NOTHING_TO_PRINT);
logger.info("##########################################################################");
}
}
|
cs |
위 AOP 코드 요약 : joinpoint(클라이언트에서 호출되는 모든 메소드) 중에서 pointcut으로(execution) 잡은 특정 메소드만 잡아 공통 관심사로 (advice(@Around)) 로 처리.
실제 호출되는 메소드를 인자(ProceedingJoinPoint)로 받아 프록시 패턴과 같이 처리한다.
pjp.proceed() 가 실제 메소드 실행부이며,
pjp.proceed() 위 아래로 로그를 처리하는 코드가 있다.
참고 :
도서 Head first design patterns,
반응형
'back > Design Pattern' 카테고리의 다른 글
[Design pattern] Adaptor pattern (어댑터 패턴) 그리고 캡슐화 (0) | 2020.01.26 |
---|---|
[Design pattern] Builder pattern (빌더 패턴) : 객체를 정의하는 세가지 패턴 (0) | 2019.12.24 |
[Design pattern] Observer Pattern (옵저버패턴) 그리고 리스너 (0) | 2019.11.21 |
[Design pattern] Facade pattern (퍼사드패턴) (0) | 2019.11.18 |
[Design pattern] strategy pattern (스트래터지 패턴) (0) | 2019.06.04 |