반응형
01. DTO클래스
Student 클래스
package xyz.itwill07.aop;
import lombok.Data;
@Data
public class Student {
private int num;
private String name;
}
02. [핵심관심모듈] : DAO클래스 - 포함(의존)관계 : 부
(부모) StudentDAO 인터페이스
package xyz.itwill07.aop;
import java.util.List;
public interface StudentDAO {
int insertStudent(Student student);
Student selectStudent(int num);
List<Student> studentList();
}
(자식) StudentDAOImpl 클래스
package xyz.itwill07.aop;
import java.util.List;
//핵심관심모듈(Core Concern Module) : 핵심관심코드만 이용하여 메소드를 작성한 클래스
//=> 핵심관심코드 : 데이타 처리를 위한 필수적인 명령
public class StudentDAOImpl implements StudentDAO{
@Override
public int insertStudent(Student student) {
System.out.println("*** StudentDAOImpl 클래스의 insertStudent(Student student) 메소드 호출 ***");
return 0;
}
@Override
public Student selectStudent(int num) {
System.out.println("*** StudentDAOImpl 클래스의 selectStudent(int num) 메소드 호출 ***");
return null;
}
@Override
public List<Student> selectstudentList() {
System.out.println("*** StudentDAOImpl 클래스의 selectstudentList() 메소드 호출 ***");
return null;
}
}
03. [핵심관심모듈] : Service클래스 - 포함(의존)관계 : 주
(부모) StudentService 인터페이스
package xyz.itwill07.aop;
import java.util.List;
public interface StudentService {
void addStudent(Student student);
Student getStudent(int num);
List<Student> getstudentList();
(자식) StudentServiceImpl 클래스
package xyz.itwill07.aop;
import java.util.List;
import lombok.Setter;
//핵심관심모듈
@Setter
public class StudentServiceImpl implements StudentService{
private StudentDAO studentDAO;
@Override
public void addStudent(Student student) {
System.out.println("*** StudentServiceImpl 클래스의 addStudent(Student student) 메소드 호출 ***");
studentDAO.insertStudent(student);
}
@Override
public Student getStudent(int num) {
System.out.println("*** StudentServiceImpl 클래스의 getStudent(int num) 메소드 호출 ***");
return studentDAO.selectStudent(num);
}
@Override
public List<Student> getstudentList() {
System.out.println("*** StudentServiceImpl 클래스의 getstudentList() 메소드 호출 ***");
return studentDAO.selectstudentList();
}
}
04. [횡단관심모듈] : Advice클래스
StudentAdvice 클래스
package xyz.itwill07.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//횡단관심모듈(CrossCutting Concern Module) : 횡단관심코드만 이용하여 메소드를 작성한 클래스 - Advice 클래스
//=> 횡단관심코드 : 데이타 처리 명령을 제외한 보조적인 기능을 제공하는 명령
//=> 로그 처리, 보안(권한) 처리, 트렌젝션 처리, 예외 처리 등의 명령
public class StudentAdvice {
private static final Logger logger = LoggerFactory.getLogger(StudentAdvice.class);
//1.
//타겟메소드의 명령 실행전에 삽입되어 실행될 명령을 작성한 메소드 - Before Advice 메소드
// => JoinPoint : 핵심관심코드를 기준으로 횡단관심코드가 삽입되어 동작될 위치를 표현
//타겟메소드(Target Method) : 핵심관심모듈의 메소드 중 PointCut 표현식으로 지정되어 횡단관심코드를
// => PointCut 표현식 : 핵심관심모듈의 메소드 중 원하는 메소드만 지정하기 위한 언어
public void beforeLog() {
logger.info("[before]핵심관심코드 동작 전 삽입되어 실행될 횡단관심코드");
}
//2.
//타겟메소드의 명령 실행전에 삽입되어 실행될 명령을 작성한 메소드 - Before Advice 메소드
// => JoinPoint : 핵심관심코드를 기준으로 횡단관심코드가 삽입되어 동작될 위치를 표현
//타겟메소드(Target Method) : 핵심관심모듈의 메소드 중 PointCut 표현식으로 지정되어 횡단관심코드를
// => PointCut 표현식 : 핵심관심모듈의 메소드 중 원하는 메소드만 지정하기 위한 언어
public void beforeLog() {
logger.info("[before]핵심관심코드 동작 전 삽입되어 실행될 횡단관심코드");
}
//3.
//타겟메소드의 명령 실행후에 예외와 상관없이 무조건 삽입되어 실행될 명령을 작성한 메소드
// => After Advice 메소드
public void afterLog() {
logger.info("[after]핵심관심코드 동작 후 무조건 삽입되어 실행될 횡단관심코드");
}
//4.
//타겟메소드의 명령이 정상적으로 실행된 후에 삽입되어 실행될 명령을 작성한 메소드
// => After Returning Advice 메소드
public void afterReturningLog() {
logger.info("[after-returning]핵심관심코드가 정삭적으로 동작된 후 삽입되어 실행될 횡단관심코드");
}
//5.
//타겟메소드의 명령 실행시 예외가 발생된 경우에만 삽입되어 실행될 명령을 작성한 메소드
// => After Throwing Advice 메소드
public void afterThrowingLog() {
logger.info("[after-throwing]핵심관심코드 동작시 예외가 발생된 경우 삽입되어 실행될 횡단관심코드");
}
//6.
//타겟메소드의 명령이 실행 전과 후에 삽입되어 실행될 명령을 작성한 메소드
// => Around Advice 메소드
public void aroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
logger.info("[around]핵심관심코드 동작 전 삽입되어 실행될 횡단관심코드");
joinPoint.proceed();//타겟메소드 호출 - 핵심관심코드 실행
logger.info("[around]핵심관심코드 동작 후 삽입되어 실행될 횡단관심코드");
}
}
05. 💖Spring Bean Configuration File
[07-1.aop.xml]
- AopProxy 클래스 - Aspect역할하기 위해서는??? : AOP 네임스페이스 추가하기
<?xml version="1.0" encoding="UTF-8"?>
<!-- AOP 네임스페이스가 추가되었음-->
<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.xsd>">
<!-- 핵심관심모듈로 작성된 클래스를 Spring Bean으로 등록 -->
<!-- StudentDAOImpl 클래스 Spring Bean으로 등록 -->
<bean class="xyz.itwill07.aop.StudentDAOImpl" id="studentDAO"/>
<!-- StudentServiceImpl 클래스 Spring Bean으로 등록 => 클래스 내 studentDAO 필드에 StudentDAOImpl 객체 의존성 주입 -->
<bean class="xyz.itwill07.aop.StudentServiceImpl" id="studentService">
<property name="studentDAO" ref="studentDAO"/>
</bean>
<!-- 횡단관심모듈로 작성된 클래스를 Spring Bean으로 등록 -->
<bean class="xyz.itwill07.aop.StudentAdvice" id="studentAdvice"/>
<!-- Spring AOP(Aspect Oriented Programming - 관점 지향 프로그래밍) : AspectJ 컴파일러에
의해 프로그램 실행 시 핵심관심코드와 횡단관심코드가 결합(Weaving)되어 동작되기 위한 기능 제공 -->
<!-- Spring AOP 기능을 사용하기 위해서는 aspectjrt 라이브러리와 aspectjweaver 라이브러리가
프로젝트에 빌드 처리 => 메이븐 사용 : pom.xml 수정 -->
<!-- => aspectjrt 라이브러리 : runtime - 실행할 때만 사용-->
<!-- => aspectjweaver 라이브러리 : weaving - 결과물을 합쳐줌 -->
<!-- => 즉, 개발자가 핵심관심코드와 횡단관심코드를 직접 만들어 사용하기 위해서는
코드를 합치는 작업(weaving)을 해야하므로 반드시 aspectjweaver 라이브러리 필요 -->
<!-- Spring Bean Configuration File에서 Spring AOP 기능을 구현하고자 할 경우
AOP 네임스페이스를 추가하여 spring-aop.xsd 파일의 엘리먼트로 설정 -->
<!-- config: Spring AOP 관련 설정을 제공하기 위한 엘리먼트 -->
<aop:config>
<!-- aspect : 핵심관심코드에 횡단관심코드를 원하는 위치(JoinPoint)에 삽입되어 실행
되도록 설정하기 위한 엘리먼트 -->
<!-- => 횡단관심코드가 삽입될 위치(JoinPoint)를 하위 엘리먼트로 설정 -->
<!-- => 하위 엘리먼트 : before, after, after-returning, after-throwing, around -->
<!-- ref 속성 : 횡단관심모듈로 작성된 Advice 클래스에 대한 Spring Bean의 식별자
(beanName)를 속성값으로 설정 -->
<!-- studentAdvice의 클래스의 메소드를 제공받아 십입처리할게요! -->
<aop:aspect ref="studentAdvice">
<!--🖤[JoinPoint] aop:before - 핵심관심코드 실행 전-->
<!-- before : 핵심관심코드 실행 전에 횡단관심코드를 삽입하여 실행되도록 설정하기 위한 엘리먼트 -->
<!-- method 속성 : Advice 클래스의 메소드명(횡단관심코드가 작성된 메소드)을 속성값으로 설정 -->
<!-- pointcut 속성 : 핵심관심모듈의 메소드 중 횡단관심모듈의 메소드가 삽입될 타겟메소드를 지정하기 위한 PointCut 표현식을 속성값으로 설정 -->
<!-- => [execution 함수] 또는 [within 함수]에 검색패턴문자와 연산자를 사용하여 타겟메소드 지정 -->
<!-- => PointCut 표현식으로 사용 가능한 [검색패턴문자] : ..(0개 이상), *(1개 이상), ?(0개 또는 1개) -->
<!-- => PointCut 표현식으로 사용 가능한 [연산자] : !(Not), &&(And), ||(Or) -->
<!-- [execution] 함수를 이용하여 타겟메소드를 지정하는 방법 -->
<!-- => execution 함수에 메소드의 머릿부를 표현하여 타겟메소드 지정 -->
<!-- 형식)execution([접근지정자] 반환형 [패키지.클래스.]메소드명(자료형,자료형,...) -->
<!-- => 클래스 대신 인터페이스 사용 가능 - 인터페이스를 상속받은 모든 자식클래스 표현 -->
<!-- => 반환형 또는 매개변수의 자료형이 클래스(인터페이스)인 경우 패키지를 포함하여 표현 -->
<!-- => 반환형: 없음, 메소드명:핵심관심모듈 중 addStudent, 매개변수명: xyz.itwill07.aop.Student -->
<!-- <aop:before method="beforeLog" pointcut="execution(void addStudent(xyz.itwill07.aop.Student))"/> -->
<!-- <aop:before method="beforeLog" pointcut="execution(* *(..))"/> --> <!--모든 반환형, 모든 메소드, 모든 매개변수(0개이상) -->
<!-- <aop:before method="beforeLog" pointcut="execution(* xyz.itwill07.aop..*(..))"/> --><!--xyz.itwill07.aop 내에 있는(0개이상) 모든 메소드-->
<!-- <aop:before method="beforeLog" pointcut="execution(* xyz.itwill07.aop.StudentDAO.*(..))"/> --><!--xyz.itwill07.aop.StudentDAO 내에 있는(0개이상) 모든 메소드-->
<!-- <aop:before method="beforeLog" pointcut="execution(xyz.itwill07.aop.Student *(..))"/> --><!-- 반환형이xyz.itwill07.aop.Student인 모든 메소드-->
<!-- <aop:before method="beforeLog" pointcut="execution(* get*(..))"/> --><!-- get으로 시작하는 메소드 -->
<!-- <aop:before method="beforeLog" pointcut="execution(* *(int)) or execution(int *(..))"/> --><!-- 매개변수가 int 거나 반환형이 int인 경우 -->
<!-- [within] 함수를 이용하여 타겟메소드를 지정하는 방법 : 광범위한 타겟 메소드 지정하고 싶을 때 이용 -->
<!-- => Spring Bean으로 등록된 클래스(핵심관심모듈)의 모든 메소드를 타겟메소드로 지정 -->
<!-- 형식)within(패키지.클래스명) -->
<!-- => 클래스 대신 인터페이스 사용 불가능 -->
<!-- <aop:before method="beforeLog" pointcut="within(xyz.itwill07.aop.StudentDAOImpl)"/> -->
<!-- <aop:before method="beforeLog" pointcut="within(xyz.itwill07.aop.StudentServiceImpl)"/> -->
<!--🧡[pointcut] aop:pointcut - 어떤 클래스의 어떤 메소드에 널을까?-->
<!-- pointcut : 핵심관심모듈의 메소드 중 횡단관심모듈의 메소드가 삽입된 타겟
메소드를 지정하기 위한 엘리먼트 -->
<!-- => 자주 사용되는 PointCut 표현식을 저장하여 타겟메소드에 대한 정보 제공 : mybatis의 resultMap과 비슷한 기능
<!-- => [aspect 엘리먼트 선언 전]에 작성하거나 [aspect 엘리먼트의 하위 엘리먼트]로 작성 -->
<!-- => [aspect 엘리먼트의 하위 엘리먼트]로 작성하면 그 내부에서만 이용 가능 -->
<!-- expression 속성 : 타겟메소드를 지정하기 위한 PointCut 표현식을 속성값으로 설정 -->
<!-- id 속성 : PointCut 표현식을 구분하기 위한 식별자를 속성값으로 설정 -->
<aop:pointcut expression="execution(* xyz.itwill07..StudentDAO.*(..))" id="studentDAOPointCut"/>
<aop:pointcut expression="execution(* xyz.itwill07..StudentService.*(..))" id="studentServicePointCut"/>
<!-- pointcut-ref 속성 : pointcut 엘리먼트의 식별자를 속성값으로 설정 -->
<!-- <aop:before method="beforeLog" pointcut-ref="studentDAOPointCut"/> -->
<aop:before method="beforeLog" pointcut-ref="studentServicePointCut"/>
<!--🖤[JoinPoint] aop:after - 핵심관심코드 실행 후 예외 발생과 상관없이 무조건-->
<!-- after : 핵심관심코드 실행 후 예외 발생과 상관없이 무조건 횡단관심코드를 삽입
하여 실행되도록 설정하기 위한 엘리먼트 -->
<aop:after method="afterLog" pointcut-ref="studentServicePointCut"/>
<!--🖤[JoinPoint] aop:after-returning - 핵심관심코드가 정상적으로 실행된 후-->
<!-- after-returning : 핵심관심코드가 정상적으로 실행된 후 횡단관심코드를 삽입하여
실행되도록 설정하기 위한 엘리먼트 -->
<aop:after-returning method="afterReturningLog" pointcut-ref="studentServicePointCut"/>
<!--🖤[JoinPoint] aop:after-throwing - 핵심관심코드 실행시 예외가 발생된 후-->
<!-- after-throwing : 핵심관심코드 실행시 예외가 발생된 후 횡단관심코드를 삽입하여
실행되도록 설정하기 위한 엘리먼트 -->
<aop:after-throwing method="afterThrowingLog" pointcut-ref="studentServicePointCut"/>
<!--🖤[JoinPoint] aop:around - 핵심관심코드 실행 전과 후-->
<!-- around : 핵심관심코드 실행 전과 후에 횡단관심코드를 삽입하여 실행되도록 설정하기
위한 엘리먼트 -->
<aop:around method="aroundLog" pointcut-ref="studentServicePointCut"/>
</aop:aspect>
</aop:config>
</beans>
06. 실행프로그램
StudentAopApp
package xyz.itwill07.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class StudentAopApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("07-1_aop.xml");
StudentService service = context.getBean("studentService",StudentService.class);
System.out.println("======================================================");
service.addStudent(null);
System.out.println("======================================================");
service.getStudent(0);
System.out.println("======================================================");
service.getstudentList();
System.out.println("======================================================");
((ClassPathXmlApplicationContext)context).close();
}
}
반응형
'framework > spring AOP(관점지향)' 카테고리의 다른 글
[springAOP] 6. 스키마기반의 AOP 만들어 사용하기 | ExecutionTimeApp프로그램 (0) | 2024.07.31 |
---|---|
[springAOP] 5. 스키마기반의 AOP 만들어 사용하기 | Advice클래스의 매개변수 (0) | 2024.07.31 |
[springAOP] 3. AOP 만들기 전 설정할 것 (0) | 2024.07.30 |
[springAOP] 2. AOP의 용어 | springAOP의 특징 및 생성법 (0) | 2024.07.30 |
[springAOP] 1. AOP의 개요 | OOP vs AOP (0) | 2024.07.30 |