728x90
반응형
AOP Around Advice 연습예제
- Around Advice는 before, atfer, after-returning, after-throwing
네가지 advice를 모두 처리할 수 있다.
[ Spring, AOP, Log4j 환경 설정 준비 ]
1. convert to maven project
2. pom.xml 환경 설정
<dependencies>
<!-- Spring Library -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.14.RELEASE</version>
</dependency>
<!-- Log4j 라이브러리 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
<!-- AOP Library -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.1</version>
</dependency>
</dependencies>
3. src 내에 log4j.xml 생성 - scr에 만드는 이유 : class complie 시 컴파일 진행 대상이 되도록!
/log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{10} (%F:%L) - %m%n" />
</Console>
<File name="file" fileName="report.log" append="true">
<PatternLayout pattern="%d %-5p [%t] %C{10} (%F:%L) - %m%n" />
</File>
</Appenders>
<Loggers>
<Root level="warn">
<AppenderRef ref="console" />
</Root>
<!-- aop.common 하위의 패키지 이하 클래스들만 별도로 Logging 설정
: spring-config.xml에서 다른 Service들이 loggingService를 aop하고 있으므로!
- level은 info 이상 로깅되도록 하고
- root level의 로깅 정책을 이어받지 않는다는 설정을 한다.
(additivity = "false")
-->
<Logger name="aop.common" level="info" additivity="false">
<AppenderRef ref="file"/>
</Logger>
</Loggers>
</Configuration>
Spring config 생성
/spring-config.xml (aop 설정 체크!)
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<bean id="personSerivce" class="kosta.model.PersonService"></bean>
<bean id="productService" class="kosta.model.ProductService"></bean>
<!-- AOP 설정 -->
<!-- 1. 횡단 관심사항 정의 bean -->
<bean id="loggingSerivce" class="aop.common.AroundLoggingAspect"></bean>
<aop:config>
<!-- 횡단 관심 사항 대상 -->
<aop:aspect ref="loggingSerivce">
<!-- 2. pointcut 지정 -->
<aop:pointcut expression="within(kosta.model..*)" id="pt"/>
<!-- 3. advice 지정 : around 로 설정-->
<aop:around method="logging" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
</beans>
/kosta.model
Exception 존재 이유 : 프로그램 수행 시, 예외가 발생했을 때 그에 맞는 적절한 대처를 하기 위함이다!
/InventoryException.java
package kosta.model;
public class InventoryException extends Exception{
/**
* 객체 직렬화 : 메모리에 있는 object가 외부로 전송될 수 있는 상태로 만들기
* 기입 했을 경우 - 이후에 instacne varible or method 추가 시 계속 동작
* 기입 안하면 - 이후 코드 수정 시 자동으로 serial no가 생성되어, class 단계에서 문제가 발생한다.
*/
private static final long serialVersionUID = -5858290483290495200L;
public InventoryException() { }
public InventoryException(String message) {
super(message);
}
}
/PersonService.java
package kosta.model;
public class PersonService {
public void registerPerson() {
System.out.println("registerPerson");
}
//매개변수 있는 경우
public void insertId(String id) {
System.out.println("insertId: "+ id);
}
//리턴 값이 있는 경우
public String getNick() {
return "아이유";
}
}
/ProductService.java
package kosta.model;
import java.sql.SQLException;
public class ProductService {
public void registerProduct() {
System.out.println("registerProduct");
}
//매개변수 있는 경우
public void insertProduct(String id, String name) {
System.out.println("insertProduct: "+ id + " " + name);
}
//리턴 값이 있는 경우
public String getMaker() {
return "오뚜기";
}
//Exception Throws
public void sellProduct(int count) throws InventoryException{
if (count < 1)
throw new InventoryException("잘못된 상품 수");
System.out.println("sell " + count);
}
//SQL Exception
public void buyProduct(int count) throws SQLException{
if (count < 1)
throw new SQLException();
System.out.println("buy " + count);
}
}
/aop.common
횡단 관심사항 정의 클래스 + Around Advice 적용
/AroundLoggingAspect.java
package aop.common;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import kosta.model.InventoryException;
//횡단 관심사항 정의 클래스
public class AroundLoggingAspect {
Logger log = LogManager.getLogger(AroundLoggingAspect.class);
//ProceedingJoinPoint : JoinPoint보다 세밀한 조정 가능
public Object logging(ProceedingJoinPoint point) throws Throwable {
// class의 method에 매개변수가 있는 경우 출력하여 확인할 수 있다.
Object params[] = point.getArgs();
for (int i = 0; i < params.length; i++) {
System.out.println("* AOP parameter: "+ params[i]);
}
// core concern에 return 값이 있는 경우
System.out.println("> AOP Before Advice ");
Object retValue = null;
try {
//proceed() : 실제 대상(target method)을 실행
// -> core concern 을 실행시킴
retValue = point.proceed();
// After-returning advice : 대상 메서드의 리턴값 제어
// instanceof : 데이터 타입이 같은지 확인하는 keyword
if(retValue != null && retValue instanceof String
&& retValue.equals("아이유")) {
retValue += "> After-returning Advice ";
}
// After-throwing advice : 대상 메서드의 예외 및 에러를 제어
} catch (InventoryException ie) {
System.out.println("> After-throwing Advice: 재고부족으로 공급처에 메시지 전달");
throw ie;
} catch (Throwable e) {
//System.out.println(e.getMessage());
throw e; //기존 흐름 그대로 유지
} finally {
//After adivce : 예외발생 유무 관련없이 무조건 실행
String cn = point.getTarget().getClass().getName();
String mn = point.getSignature().getName();
System.out.println("> After Advice: " + cn + "|" + mn);
//log.info("AOP : " + cn + " | " + mn);
}
return retValue;
}
}
/test
/TestAOP.java
package test;
import java.sql.SQLException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import kosta.model.InventoryException;
import kosta.model.PersonService;
import kosta.model.ProductService;
public class TestAOP {
public static void main(String[] args) {
ClassPathXmlApplicationContext factory
= new ClassPathXmlApplicationContext("spring-config.xml");
PersonService person = (PersonService) factory.getBean("personSerivce");
person.insertId("java");
System.out.println(person.getNick());
person.registerPerson();
System.out.println("-----------------------------------------");
ProductService product = (ProductService) factory.getBean("productService");
product.registerProduct();
product.insertProduct("java", "book");
System.out.println(product.getMaker());
//Exception 발생하는 메서드
try {
product.sellProduct(-3);
} catch (InventoryException e) {
System.out.println("Excpetion 전달받아 메인에서 예외처리");
System.out.println("main: "+ e.getMessage());
}
try {
product.buyProduct(-1);
} catch (SQLException e) {
System.out.println("buy에서 SQLException 발생해서 메인에서 예외처리");
}
factory.close();
}
}
[ 결과 ]
728x90
반응형
'Java Web Programming > 6. Spring | MyBatis' 카테고리의 다른 글
[Spring] 스프링 AOP의 Around Advice를 통한 성능 확인 (+Log4j, StopWatch 라이브러리) (0) | 2020.10.29 |
---|---|
[Spring] 스프링 스탑워치(StopWatch) 라이브러리 사용법 (0) | 2020.10.29 |
[Spring] Logging 로깅 - Log4j (스프링 AOP 방식 적용) (0) | 2020.10.28 |
[Spring] 스프링 AOP 개념 이해와 적용 방법 (+Proxy 프록시) (0) | 2020.10.28 |
[Spring] DBCP를 Spring config로 설정해보기! (+IOC/DI+DL) (0) | 2020.10.27 |