[문제]
1. around
board S_ALL
member S_ALL
수행시간을 비교하는 공통로그를 호출
2. before, after
회원가입 전후로 로그 출력
before >> 메서드명을 출력
after >> 인자를 출력(누가 가입했는지 출력)
3. returning, throwing
로그인한 회원이 관리자라면,
관리자가 로그인했습니다. 라고 출력
만약 일반회원이 로그인했다면
예외 발생
그리고 그 예외가 발생했음을 알리는 공통로그를 출력
공통적인 기능 즉, 횡단 관심이므로 따로 Advice로 분리하는데
모든 문제가 다 로그를 출력하는 공통적인 역할을 하기 때문에 하나의 클래스로 작성했다.
→ 코드의 응집도 향상.
1. LogAdvice
package com.example.biz.common;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
import com.example.biz.member.MemberVO;
// 모두 로그를 출력하는 메서드이므로 하나의 클래스 안에 작성
public class LogAdvice {
// 1-1. s-all 수행시간을 비교하는 공통로그
public Object timeLog(ProceedingJoinPoint pjp) {
Object obj = null;
StopWatch sw = new StopWatch();
// 필요 시에는 new 해도 ok
// 서비스 시작
sw.start();
try {
obj = pjp.proceed();
} catch(Throwable e) {
e.printStackTrace();
}
sw.stop(); // 시간 측정 끝
Long time = sw.getTotalTimeMillis();
System.out.println("수행 시간 : ["+time+"]");
return obj;
}
// 2. 회원가입 전후로 로그 출력(before, after)
// 2-1. before
public void beforeLog(JoinPoint jp) {
String methodName = jp.getSignature().getName();
System.out.println("메서드 시그니쳐 출력 : ["+methodName+"]");
}
// 2-2. after
public void afterLog(JoinPoint jp) {
Object[] args = jp.getArgs();
System.out.println("인자 출력 : [");
for(Object arg : args) {
System.out.println(arg);
}
System.out.println("]");
}
//3-1. returning
/*public void returningLog(Object returnObj) {
if (returnObj instanceof MemberVO membervo) {
if ("ADMIN".equals(membervo.getMrole())) {
System.out.println("관리자가 로그인했습니다.");
} else {
System.out.println("일반회원 로그인!");
}
}
}*/
// 3-1. returning
public Object returningLog(ProceedingJoinPoint pjp) throws Throwable {
Object obj = null;
try {
obj = pjp.proceed();
if(obj instanceof MemberVO) { // 타입 확인
MemberVO vo = (MemberVO) obj; // 다운캐스팅
if(vo.getMrole().equals("ADMIN")) {
System.out.println("관리자가 로그인 했습니다.");
} else { // 관리자가 아닌 경우 예외 발생
throw new IllegalArgumentException("일반회원 로그인!");
}
}
} catch (IllegalArgumentException e) { // 예외처리
System.out.println("일반회원 로그인 예외처리");
return null;
}
return obj;
}
// 3-2. throwing
public void throwingLog(JoinPoint jp, Exception exceptObj) {
if(exceptObj instanceof IllegalArgumentException) { // 예외라면
System.out.println("일반회원 로그인! 예외 발생!");
} else {
System.out.println("확인되지 않은 예외");
}
}
}
2. applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.example.biz.board.impl" />
<context:component-scan base-package="com.example.biz.member.impl" />
<context:component-scan base-package="com.example.biz.common"/>
<!-- 1. 빈(Bean) 등록 -->
<bean id = "LogAdvice" class="com.example.biz.common.LogAdvice"/>
<!-- 2. AOP 설정 -->
<aop:config>
<!-- 문제 1 : 포인트컷 -->
<aop:pointcut id="timeAround" expression="execution(* com.example.biz..*ServiceImpl.get*List(..))"/>
<!-- 문제 2 : 포인트컷 -->
<aop:pointcut id = "join" expression="execution(* com.example.biz.member.impl.MemberServiceImpl.insert(..))"/>
<!-- 문제 3 : 포인트컷 -->
<aop:pointcut id = "login" expression="execution(* com.example.biz.member.impl.MemberServiceImpl.getMember(..))"/>
<aop:aspect ref="LogAdvice">
<!-- 문제 1 : 애스택트 - AROUND -->
<aop:around method = "timeLog" pointcut-ref = "timeAround"/>
<!-- 문제 2: 애스팩트 - BEFORE/AFTER -->
<aop:before method = "beforeLog" pointcut-ref="join"/>
<aop:after method = "afterLog" pointcut-ref="join"/>
<!-- 문제 3 : 애스팩트 - RETURNING/THROWING -->
<aop:around method="returningLog" pointcut-ref="login"/>
<aop:after-throwing method = "throwingLog" pointcut-ref ="login" throwing = "exceptObj"/>
</aop:aspect>
</aop:config>
</beans>
자꾸 applicationContext.xml에서 xsd 파일들을 인식못했는데..
Eclipse는 기본적으로 외부 사이트 접속해서 XSD 파일을 자동으로 다운받지 않는다.
따라서 [preference] → [XML catalog]에 들어가서 [Download external resources like referenced DTD, XSD]를 체크해주었더니 해결.
'웹 개발' 카테고리의 다른 글
Eclipse와 VSCode (0) | 2025.04.26 |
---|---|
Map 등을 DI 할 수는 없을까? (0) | 2025.04.25 |
AOP (0) | 2025.04.23 |
이메일 API 코드를 Spring Boot로 변환할 때 경고 처리 (0) | 2025.04.22 |
JSP/Servlet → Spring Boot 이관 중 배운 점 (0) | 2025.04.21 |