kh day 115
public class LogAdvice { // POJO : Plain Old Java Object
// @Before : JoinPoint 메소드 실행 전 동작
// POINTCUT EXPRESSION 생성은, AsepectJ 언어에서 제공하는 함수를 이용
// 이 pointcut 설정함수 이름은 "execution()"
// 이 execution 함수를 호출시, pointcut 설정내역을 인자값으로 매개변수에 전달해야함
@Before( "execution( * org.zerock.myapp.service.*Service.*(..) )" )
// 모든 접근제한자의 Service로 끝나는 모든 클래스의 모든 메서드의 모든 매개변수(..)에 적용
public void logBefore() {
log.trace("==============================");
log.trace("1. logBefore() invoked.");
log.trace("==============================");
} // logBefore
// 위는 단순한 호출로그다 인자값을 넣어보자. (&& args() 활용)
// @Before JoinPoint 메소드 실행 전 동작
@Before( "execution( * org.zerock.myapp.service.*Service.doAdd(..) ) && args (op1, op2) " )
// 모든 접근제한자의 Service로 끝나는 모든 클래스의 doAdd 메서드의 모든 매개변수(..)에 적용 && 인자값 대입
public void logBeforeWithArgs(String op1, String op2) {
log.trace("==============================");
log.trace("2. logBeforeWithArgs({}, {}) invoked.", op1, op2);
log.trace("==============================");
} // logBeforeWithArgs
// @AfterReturning : JoinPoint 메소드 정상 실행 후 동작
// @AfterReturning( "execution( * org.zerock.myapp.service.*Service.*(..) )" )
// 모든 접근제한자의 Service로 끝나는 모든 클래스의 모든 메서드의 모든 매개변수(..)에 적용
// public void logAfterReturning() {
// log.trace("==============================");
// log.trace("3. logAfterReturning() invoked.");
// log.trace("==============================");
//
// } // logAfterReturning
// 위는 단순 호출로그다 인자 값을 넣어보자
// @AfterReturning : JoinPoint 메소드 정상 실행 후 동작
@AfterReturning( pointcut = "execution( * org.zerock.myapp.service.*Service.*(..) )", returning = "result" )
// 모든 접근제한자의 Service로 끝나는 모든 클래스의 모든 메서드의 모든 매개변수(..)에 적용
public void logAfterReturning(Object result) { // doAdd의 리턴값 -> Integer 300이 자동형변환 되서 Object 부모에 안김
log.trace("==============================");
log.trace("3. logAfterReturning({}, type : {}) invoked.", result, result.getClass().getName());
log.trace("==============================");
} // logAfterReturning
} // end class
LogAdvice
JointPoint인 doAdd 메소드 실행 전 후에 실행되는걸 확인하자
--
이번에는 고의로 exception을 발생시키고 이를 @AfterThrowing으로 처리해보자
테스트메소드 매개변수 "이백"으로 변경하셈
// @AfterThrowing : JoinPoint 메소드에서 예외 발생 후 동작
@AfterThrowing( pointcut = "execution( * org.zerock.myapp.service.*Service.*(..) )", throwing = "e" )
// 모든 접근제한자의 Service로 끝나는 모든 클래스의 모든 메서드의 모든 매개변수(..)에 적용
public void logAfterThrowing(Exception e) {
log.trace("==============================");
log.trace("3. logAfterThrowing({}) invoked.", e);
log.trace("==============================");
} // logAfterThrowing
LogAdvice
@AfterThrowing 메소드
콘솔창 (예외의 스택트레이스가 호출된다)
---
// @After : JoinPoint 메소드 실행 후 무조건 동작(정상실행 되나 예외발생하나 상관x)
@After( "execution( * org.zerock.myapp.service.*Service.*(..) )" )
// 모든 접근제한자의 Service로 끝나는 모든 클래스의 모든 메서드의 모든 매개변수(..)에 적용
public void logAfter() {
log.trace("==============================");
log.trace("4. logAfter({}) invoked.");
log.trace("==============================");
} // logAfter
LogAdvice
@After 메소드
콘솔창 (200으로 실행한거 하나 이백으로 실행한거 하나)
예외가 발생하던, 정상실행하던 얘는 무조건 실행된다
----
***
LogAdvice
@Around 메소드
// @Around를 위한 메소드를 추가해주자
public abstract void methodForAroundAdvice() throws Exception;
sampleservice.java에 메소드 추가해주자
// @Around를 위한 메소드
@Override
public void methodForAroundAdvice() throws Exception {
log.info("methodForAroundAdvice() invoked.");
} // methodForAroundAdvice
sampleserviceimpl에 구현 메소드? 만들어주자
@Test
@Order(2)
@DisplayName("2. SampleService.methodForAroundAdvice")
@Timeout(value = 10, unit = TimeUnit.SECONDS)
void testMethodForAroundAdvice() throws Exception {
log.trace("testMethodForAroundAdvice() invoked.");
this.service.methodForAroundAdvice();
} // testMethodForAroundAdvice
tests에 두번째 메소드 만들어주자
// @Around : Target 객체의 JointPoint의 실행여부까지 책임지며, JoinPoint를 실행시킨경우
// 실행 전/후에 적용할 기능까지 함께 구현 가능 (혼자 북치고 장구치고 다 한다)
// @Around 는 ProceedingJoinPoint와 함께 결합하여 동작한다
@Around( "execution( * org.zerock.myapp.service.*Service.methodForAroundAdvice(..) )" )
// 모든 접근제한자의 Service로 끝나는 모든 클래스의 methodForAroundAdvice 메서드의 모든 매개변수(..)에 적용
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
log.trace("==============================");
log.trace("6. logAround({}, type:{}) invoked.", pjp, pjp.getClass().getName());
log.trace("==============================");
Object target = pjp.getTarget(); // JoinPoint가 있는 Target 객체
Signature signature = pjp.getSignature(); // JoinPoint의 Method Signature
Object[] args = pjp.getArgs(); // JonPoint의 매개변수들을 배열로 변환
log.info("\t+ 1. target : {}", target);
log.info("\t+ 2. signature : {}", signature);
log.info("\t+ 3. args : {}", Arrays.toString(args));
// AOP로 로그뿐만 아니라 실행속도 같은 걱정거리도 처리할 수 있다.
long start = System.nanoTime(); // 10억분의 1초
// long start = System.currentTimeMillis(); // 1000분의 1초
Object returnValue = pjp.proceed(); // JoinPoint인 methodForAroundAdvice 메서드를 실행시켜라!
long end = System.nanoTime(); // 10억분의 1초
// long end = System.currentTimeMillis(); // 1000분의 1초
log.info("\t+ 4. Elapsed time : {} seconds", (end - start) / Math.pow(10, 9) ); // 10억분의 1초
// log.info("\t+ 4. Elapsed time : {} seconds", (end - start) / Math.pow(10, 3) ); // 1000분의 1초
return returnValue;
} // logAround
LogAdvice
@Around 메소드
콘솔창
---
chap19 스프링 트랜잭션
public interface Sample1Mapper {
@Insert("INSERT INTO tbl_sample1 (col) VALUES ( #{col} )")
public abstract void insertCol( @Param("col") String data) throws Exception;
} // end interface
Sample1Mapper
public interface Sample2Mapper {
@Insert("INSERT INTO tbl_sample2 (col) VALUES ( #{col} )")
public abstract void insertCol( @Param("col") String data) throws Exception;
} // end interface
Sample2Mapper (@Param 이해하고 넘어가자)
public interface SampleTXService {
public abstract void 계좌이체(String data) throws Exception;
} // end interface
SampleTXService
@Log4j2
@NoArgsConstructor
@Service
public class SampleTXServiceImpl implements SampleTXService, InitializingBean {
// 주입
@Setter(onMethod_= @Autowired)
private Sample1Mapper mapper1;
// 주입
@Setter(onMethod_= @Autowired)
private Sample2Mapper mapper2;
@Override
public void 계좌이체(String data) throws Exception {
log.info("계좌이체() invoked.");
// 1. 소스계좌에서 이체금액만큼 차감 (DML 문장수행)
this.mapper1.insertCol(data);
// 2. 타겟계좌로 이체금액만큼 추가 (DML 문장수행)
this.mapper2.insertCol(data);
} // 계좌이체
@Override
public void afterPropertiesSet() throws Exception {
log.trace("afterPropertiesSet() invoked.");
log.info("\t+ this.mapper1 : {}, type : {}", this.mapper1, this.mapper1.getClass().getName());
log.info("\t+ this.mapper2 : {}, type : {}", this.mapper2, this.mapper2.getClass().getName());
} // afterPropertiesSet
} // end class
SampleTXServiceImpl
@Log4j2
@NoArgsConstructor
//JUnit5 방식
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@TestInstance(Lifecycle.PER_CLASS)
public class SampleTXServiceTests {
// 주입
@Setter(onMethod_=@Autowired)
private SampleTXService service;
// 주입이 되었는지 1회성 전처리 과정을 통해 확인하자
@BeforeAll
void beforeAll() {
log.trace("beforeAll() invoked.");
// 주입이 되었는지 확인 (주입이 되었다면 null이 아님)
assertNotNull(this.service);
log.info("\t+ this.service : {}", this.service);
log.info("\t+ type : {}", this.service.getClass().getName());
} // beforeAll
@Test
@Order(1)
@DisplayName("1. test계좌이체")
@Timeout(value = 10, unit = TimeUnit.SECONDS)
void test계좌이체() throws Exception {
log.trace("test계좌이체() invoked.");
// 0. 이체금액 정의
String transferMoney = "123456789012345678901234567890123456789012345678901"; // length : 51;
this.service.계좌이체(transferMoney);
log.info("계좌이체가 잘 되었습니다.");
} // test계좌이체
} // end class
SampleTXServiceTests
51 바이트를 집어 넣었는데, 1번 테이블은 100바이트 용량이라 성공적으로 들어갔고, 2번 테이블은 50바이트 용량이라 들어가지 않았다. 이런 경우 둘다 들어가지 않게끔 할 수 없을까?!
@Transactional // TX 처리 수행 (All or Nothing)
@Override
public void 계좌이체(String data) throws Exception {
log.info("계좌이체() invoked.");
// 1. 소스계좌에서 이체금액만큼 차감 (DML 문장수행)
this.mapper1.insertCol(data);
// 2. 타겟계좌로 이체금액만큼 추가 (DML 문장수행)
this.mapper2.insertCol(data);
} // 계좌이체
impl에 @Transactional 추가해주자
이제 이런 경우 1번 테이블에 들어갔다가 롤백되서 결과적으로 둘 다 안 들어가게 된다!
이걸로 스프링도 끝 수고했습니다.
'국비학원' 카테고리의 다른 글
[국비지원] KH 정보교육원 117일차 (0) | 2022.09.14 |
---|---|
[국비지원] KH 정보교육원 116일차 (0) | 2022.09.14 |
[국비지원] KH 정보교육원 114일차 (0) | 2022.09.08 |
[국비지원] KH 정보교육원 113일차 (0) | 2022.09.07 |
[국비지원] KH 정보교육원 110-112일차 (0) | 2022.09.05 |