AOP(Aspect Oriented Programming) : 관점지향 프로그램
📍개념 : 로그 처리, 보안, 트랜잭션 관리 그리고 예외사항 처리 등의 코드를 단일 모듈로 각각 작성하고 필요한 시점에 핵심코드를 삽입하여 동작하게 하는 것
- 횡단관심코드를 미리 만들어 놓고 필요할 때마다 코드를 합쳐서 프로그램을 만드는 것
📍목적 : OOP와 같은 모듈화가 뛰어난 방법을 사용하더라도 결코 쉽게 분리된 모듈로 작성하기 힘든 요구사항이 실제 어플리케이션 설계와 개발에서 자주 발견됨(중복된 코드를 최소화하기 위함)
→ AOP에서는 이를 횡단 관심 코드라고 한다.

< 수업순서 2024.08.26 >
1. OopOne
Oop의 문제점 : 모듈화(캡슐화)가 너무 강력하여 핵심관심코드와 횡단관심코드를 분리하여 프로그램을 작성하기 어려움
- 추상화(캡슐화) : 하나의 대상을 클래스로 만드는 것
2. OopApp : 명령 출력
3. OopTwo
4. OopLogger : 핵심관심코드 실행전에 기록될 메소드(beforeLog) 작성
Spring AOP
: AspectJ 컴파일러에 의해 프로그램 실행시 핵심관심코드와 횡단관심코드가 결합(Weaving)되어 실행되는 기능 제공
핵심관심코드 : 프로그램 실행에 핵심적인 기능을 제공하는 명령 - 데이터 처리 명령
횡단관심코드 : 데이터 처리 명령을 제외한 보조적인 기능을 제공하는 명령(로그 처리, 보안 처리, 트랜잭션, 예외 처리 등)
5. AopOne : 핵심관심코드만 사용하여 작성된 메소드가 선언된 클래스 - 핵심관심모듈 / AopTarget 인터페이스 상속
6. AopTwo : 핵심관심모듈 / AopTarget 인터페이스 상속
7. AopTarget 인터페이스 : 횡단관심코드가 삽입될 핵심관심코드의 메소드를 추상메소드로 선언 - PointCut(타겟메소드를 지정하기 위한 규칙)


8. AopLogger : 횡단관심코드의 메소드가 작성된 클래스 - 횡단관심모듈 : Advice 클래스
9. AopProxy : 핵심관심코드에 횡단관심코드가 삽입된 메소드가 선언된 클래스 - Proxy 클래스 : Aspect(핵 & 횡 결합되어 만들어진 것)

10. AopApp : 명령 출력
11. Hewon : 필드 작성, @Data Lombok 사용
12. HewonDAO : 추상메소드 작성
13. HewonDAOImpl(핵심관심모듈 : 핵심관심코드의 메소드가 작성된 클래스) : HewonDAO 인터페이스 상속 / 메소드 오버라이드
14. HewonService 인터페이스 : 추상메소드 작성
15. HewonServiceImpl(핵심관심모듈) : HewonService 인터페이스 상속 / 메소드 오버라이드
16. HewonApp : 명령 출력
17. 06-1_aop.xml
-
핵심관심모듈의 클래스(DAO 클래스 및 Service 클래스)를 Spring Bean으로 등록 - 의존성 주입
- HewonServiceImpl 클래스 : Setter 메소드 의존성 주입(property 엘리먼트)

-
횡단관심모듈의 클래스(Advice 클래스)를 Spring Bean으로 등록

-
Spring AOP 기능을 사용하기 위해서는 aspectjrt 라이브러리와 aspectjweaver 라이브러리 필요 - 메이븐 : pom.xml 변경
- 기존 aspectj-version과 같은 version으로 추가

- pom.xml에서 확인

- pom.xml에 dependency 추가

-
Spring Bean Configuration File(XML)에서 Spring AOP 기능을 구현하기 위한 엘리먼트를 사용하기 위해 aop 네임스페이스를 추가해 spring-aop.xsd 파일을 제공받도록 설정

< Spring AOP 기능을 구현하기 위한 엘리먼트 >
config : Spring AOP 기능을 구현하기 위한 정보를 제공하기 위한 엘리먼트
→ 하위 엘리먼트 : advisor, aspect(횡단), pointcut(핵심) 엘리먼트
-
aspect : 핵심관심코드에 횡단관심코드를 원하는 위치에 삽입하여 실행되도록 설정하기 위한 엘리먼트
→ 하위 엘리먼트 : before, after-returning, after-throwing, after, around 엘리먼트
-
ref 속성 : 횡단관심모듈(Advice 클래스)의 식별자(beanNAme)을 속성값으로 설정
→ 횡단관심코드(HewonAdvice)의 메소드를 호출하기 위한 객체를 제공받아 이용

-
before : 타겟메소드의 명령(핵심관심코드) 실행 전 횡단관심코드를 삽입해 실행되도록 설정하기 위한 엘리먼트
- method 속성 : 횡단관심모듈(Advice 클래스)의 메소드명을 속성값으로 설정
- pointcut 속성 : 핵심관심모듈로 등록된 Spring Bean의 메소드 중 횡단관심코드가 삽입될 타겟메소드를 지정하기 위한 Pointcut 표현식을 속성값으로 설정(타겟메소드 지정)
- Pointcut 표현식 : Pointcut 언어를 사용해 클래스에 작성된 메소드 중 타겟메소드를 지정하기 위한 표현 방법(execution, within, bean 제한자(패턴문자 포함) 및 연산자를 사용해 타겟메소드가 지정되도록 설정)
- execution 제한자 형식 : execution([접근제한자] 반환형 [패키지명.클래스명.]메소드명(자료형,자료형,...))
- within 제한자 형식 : within(패키지명.클래스명)
- bean 제한자 형식 : bean(beanName)
-
pointcut : Spring Bean으로 등록된 클래스(핵심관심모듈)의 메소드 중 횡단관심코드가 삽입될 타겟메소드 정보를 설정하기 위한 엘리먼트
- expression 속성 : 타겟메소드를 지정하기 위한 제한자를 속성값으로 설정
- id 속성 : pointcut 엘리먼트를 구분하기 위한 식별자를 속성값으로 설정

-
pointcut-ref 속성(before 엘리먼트 속성) : pointcut 엘리먼트의 식별자(id 속성값)를 속성값으로 설정

➡️ pointcut 엘리먼트로 횡단관심코드가 삽입될 타겟메소드 정보를 설정하여 pointcut 엘리먼트의 id 속성값을 before 엘리먼트 point-ref 속성값으로 가져와 타켓메소드 정보 등록
-
after-returning : 타켓메소드의 명령(핵심관심코드)이 예외 없이 정상적으로 실행된 후에 횡단관심코드를 삽입해 실행되도록 설정하기 위한 엘리먼트
-
after-throwing : 타겟메소드의 명령(핵심관심코드) 실행시 예외가 발생된 후에 횡단관심코드를 삽입해 실행되도록 설정하기 위한 엘리먼트
-
after : 타겟메소드의 명령(핵심관심코드)이 실행된 후 무조건 횡단관심코드를 삽입해 실행되도록 설정하기 위한 엘리먼트
-
around : 타겟메소드의 명령(핵심관심코드)이 실행 전과 후에 횡단관심코드를 삽입해 실행되도록 설정하기 위한 엘리먼트
-
HewonApp 출력 콘솔⬇️(* after-throwing은 예외가 발생하지 않아서 출력되지 않음)

18. HewonAdvice(횡단관심모듈) : 횡단관심코드의 메소드가 작성된 클래스 - Advice 클래스
19. JoinPointBean(핵심관심모듈) : 메소드 5개 작성
20. JoinPointApp : 명령 출력
21. 06-2_param

22. JoinPointAdvice(횡단관심모듈)
-
JoinPoint 객체 : 타겟메소드 관련 정보가 저장된 객체
-
AspectJ 컴파일러에 의해 Advice 클래스의 메소드가 호출될 때 타겟메소드 관련 정보가 저장된 JoinPoint 객체를 전달받아 매개변수에 저장
-
Befor Advice Method
-
JoinPoint.getTarget() : 타겟메소드를 호출한 객체(핵심관심모듈
-
Spring Bean)를 Object 객체로 반환하는 메소드- Object.getClass() : 객체를 생성한 클래스 정보가 저장된 Class 객체를 반환하는 메소드
-
Class.getName() : Class 객체의 클래스(패키지 포함)의 이름을 문자열로 반환하는 메소드


-
Class.getSimpleName() : Class 객체의 클래스(패키지 미포함)의 이름을 문자열로 반환하는 메소드


-
JoinPoint.getSignature() : 타겟메소드 정보가 저장된 Signature 객체를 반환하는 메소드
-
Signature.getName() : 타겟메소드의 이름을 반환하는 메소드


-
joinPoint.getArgs() : 타겟메소드의 매개변수에 저장된 모든 값(객체)를 Object 배열로 반환하는 메소드


-
클래스명, 메소드명, 타겟메소드의 매개변수에 저장된 모든 값 저장하여 출력.


-
After Advice Method


-
After Returning Advice Method
- JoinPoint 외에 매개변수를 하나 더 쓸 수 있다. Object type으로 매개변수를 지정하면 타겟메소드의 반환값이 어느 type이든 저장 가능.(반환값의 type을 알 경우는 type 지정하면 됨)
-
After Throwing Advice Method
- JoinPoint 인터페이스의 매개변수 외에 Exception 클래스의 매개변수 작성 가능, 예외 객체를 저장할 수 있는 매개변수

- After Returning Advice Method에 Object 클래스의 매개변수를 작성한 경우 Spring Bean Configuration File의 AOP 설정에서 after-returning 엘리먼트에 returning 속성을 반드시 작성해 타겟메소드의 반환값이 매개변수에 저장되도록 설정
-
Around Advice Method
- 반환형은 무조건 Object 객체, 매개변수는ProceedingJoinPoint라는 인터페이스로 지정
- ProceedingJoinPoint 객체 : 타겟메소드(핵심관심코드) 관련 정보를 저장하기 위한 객체
- ProceedingJoinPoint.proceed() : ProceedingJoinPoint 객체로 타겟메소드를 호출하는 메소드 → 타겟메소드를 호출해 반환되는 결과값을 변수에 저장하여 반환
- Throwable : Error 클래스의 Exception 클래스의 부모클래스로 모든 오류를 다 잡아냄

➡️설명 : 최종 JoinPointApp 출력 콘솔, 일부러 예외를 발새이켜 after-throwing 출력
< 수업 순서 - 2024.08.27 >
23. ExecutionTimeBean : 핵심관심묘듈(메소드 2개 작성) - 핵심관심코드가 실행되는 시간 기록
24. ExecutionTimeApp : 명령 출력
25. 06-3_timer.xml : 핵심관심모듈, 횡단관심모듈 클래스를 Spring Bean으로 등록하고 AOP 엘리먼트로 Around 기능 사용

➡️설명 : Spring Bean Configuration File(xml 파일)에 핵심, 횡단관심모듈의 클래스를 Spring Bean으로 등록하고 AOP 기능을 사용하기 위해 aop:config 엘리먼트 추가.
➡️설명 : aop:config 엘리먼트의 하위 엘리먼트로 aspect 엘리먼트를 추가하여 핵심관심코드에 횡단관심코드를 원하는 위치에 삽입하여 실행되도록 설정. aspect 엘리먼트의 ref 속성값으로 횡단관심모듈의 클래스 beanName을 입력.
➡️설명 : aspect 엘리먼트의 하위 엘리먼트인 around 엘리먼트로 타겟메소드의 명령(핵심관심코드) 실행 전과 후에 횡단관심코드를 삽입해 실행되도록 설정.(method 속성 : 횡단관심모듈의 메소드명 입력, pointcut 속성 : 타겟메소드 지정 Pointcut 표현식 입력)
➡️설명 : pointcut 속성은 핵심관심코드의 메소드 지정
26. ExecutionTimeAdvice : 횡단관심묘듈
- Advice 클래스에서 사용하는 어드바이스를 Spring Bean Configuration File에 등록해주어야 이용할 수 있다.


27. EmailSendBean : 핵심관심모듈 - 메일 전송 기능(JavaMail)을 제공하기 위한 클래스
- 메일 서버 : 메일을 송수신하는 서비스를 제공하는 컴퓨터
- 메일 서버는 SMTP 서비스(Simple Message Transfer Protocl - 25)를 이용해 메일을 전송하고 POP3(Post Office Protocol3 - 110) 서비스 또는 IMAP(Internet Message Access Protocol - 143) 서비스를 이용해 메일을 수신하여 사용자에게 전달
- 도메인, 도메인서버(DNS Server),
- JavaMail 기능을 구현하기 위해 spring-context-support 라이브러리와 javax.mail 라이브러리를 프로젝트에 빌드 처리
- pom.xml 파일에 dependency 엘리먼트 추가


- version은 spring-framework-version과 동일하게 설정


< 코드 설명 >
➡️설명 : JavaMailSender 객체를 저장하기 위한 필드를 작성하고 Configuration File에서 Dependency Injection하여 SMTP 서비스를 제공하는 정보를 저장

➡️설명 : JavaMailSender 객체를 사용하여 메일 전송하는 메소드 작성

➡️설명
- JavaMailSender.createMimeMessage() : JavaMailSender 객체로 MimeMessage 객체를 생성하여 반환하는 메소드
- MimeMessage 객체 : 메일 전송 관련 정보를 저장하기 위한 객체

- MimeMessage.setSubject(String subject) : MimeMessage 객체의 메일 제목을 변경하는 메소드

- MimeMessage.setContent(Object o, String type) : MimeMessage 객체의 메일 내용을 변경하는 메소드

- MimeMessage.setRecipient(RecipientType type, Address address) or .setRecipients(RecipientType type, Address[] address) : MimeMessage 객체의 메일을 받는 사람 or 사람들의 이메일 주소 관련 정보를 변경하는 메소드

- JavaMailSender.send(MimeMessage message) : 매개변수로 전달받은 MimeMessage 객체의 정보를 사용해 JavaMailSender 객체(SMTP)로 메일을 전송하는 메소드

28. EmailSendApp : 명령 실행

-
출력 콘솔

-
이메일 전송 완료

29. 06-4_email.xml
- 핵심, 횡단관심모듈 클래스를 Spring Bean으로 등록
- Advice 클래스에서 사용한 어드바이스 엘리먼트 추가

30. EmailSendAdvice : 횡단관심모듈

➡️설명 : 메일 전송 전, 전송 성공 후, 전송 실패 후 삽입되어 실행될 명령이 작성된 메소드 생성
31. AopAnnotationBean : 핵심관심모듈
32. AopAnnotationApp : 명령 실행
33. 06-5_aopAnnotation.xml : aspectj-autoproxy 엘리먼트 설정
- aspectj-atuoproxy : AOP 관련 어노테이션을 사용하여 Aspect(Proxy 클래스)를 생성해 제공하기 위한 기능을 제공하는 어노테이션
34. AopAnnotationAdvice : 횡단관심모듈 - 어노테이션으로 어드바이스 설정
-
@Compont : 해당 클래스를 Spring 컨테이너에서 관리할 수 있게 Spring Bean으로 등록해주는 어노테이션
-
@Aspect : 핵심관심코드에 횡단관심코드를 삽입하여 실행하기 위한 기능을 제공하는 어노테이션
-
@Pointcut : 타겟메소드를 지정하기 위한 어노테이션
- value 속성 : 타겟메소드를 지정할 수 있는 Pointcut 표현식을 속성값으로 설정

-
@Before : 타겟메소드의 명령(핵심관심코드)이 실행되기 전에 삽입되어 실행될 횡단관심코드를 제공하기 위한 어노테이션
→ @Pointcut 어노테이션을 사용한 메소드를 호출하여 Pointcut 표현식을 제공받아 타겟메소드 지정 가능(타겟메소드 제공받을 수 있음)

-
@After : 타겟메소드의 명령(핵심관심코드)이 실행된 후에 삽입되어 실행될 횡단관심코드를 제공하기 위한 어노테이션

-
@AfterReturning : 타겟메소드의 명령(핵심관심코드)이 정상적으로 실행된 후에 삽입되어 실행될 횡단관심코드를 제공하기 위한 어노테이션

-
@AfterThrowing : 타겟메소드의 명령(핵심관심코드)이 실행시 예외가 발생된 후에 삽입되어 실행될 횡단관심코드를 제공하기 위한 어노테이션

-
@Around : 타겟메소드의 명령(핵심관심코드)이 실행 전과 후에 삽입되어 실행될 횡단관심코드를 제공하기 위한 어노테이션


➡️최종 명령 실행 콘솔, after-throwing 어노테이션은 예외가 발생하지 않아 출력되지 않음