π κΈλ 6κΈ° ν¬μ€ν
1. λ―ΈμΉλλ‘ λμ λ 7μμ νκ³
2. μ¬μ©μκ° κ²μλ¬Όμ μμ±ν λμ νΈλμμ μ²λ¦¬
3. Spring AOP - (1) νλ‘μ ν¨ν΄, λ°μ½λ μ΄ν° ν¨ν΄
4. [MySQL] - νΈλμμ μ 격리 μμ€(Isolation level)
5. Spring AOP - (2) AOP κ°λ λ° μ€μ΅
6. μΈν 리μ μ΄(IntelliJ) - λλ²κΉ (Debugging) νκΈ°
7. [Java, λμμΈν¨ν΄] - μ±κΈν΄ ν¨ν΄(Singleton Pattern)
8. μκ° μ½λ리뷰 Ver_0.1: μ»€λ¦¬μ΄ μ±μ₯ CODE μΈλ―Έλ μ 리
9. ν¬μ€νΈλ§¨(API ν μ€νΈ) νμ©νκΈ°
π Spring AOP(Aspect Oriented Programming)
ν¬μ€ν μ μμ±ν μμ μ½λλ κΉνλΈμμ νμΈνμ€ μ μμ΅λλ€ :)
μ§λλ² μ 리ν Spring AOP - (1) νλ‘μ ν¨ν΄, λ°μ½λ μ΄ν° ν¨ν΄ ν¬μ€ν μ μ΄μ΄ λλ¨Έμ§ λͺ©μ°¨λ€μ λν΄ μ 리λ₯Ό ν΄λ³΄κ² μ΅λλ€.
ν¬μ€ν μ λͺ©μ°¨ μ λλ€.
λΆκ°κΈ°λ₯μ μμνλ μ ν΅μ μΈ λ°©λ² 1 - νλ‘μ ν¨ν΄λΆκ°κΈ°λ₯μ μμνλ μ ν΅μ μΈ λ°©λ² 2 - λ°μ½λ μ΄ν° ν¨ν΄- Spring AOP κ°λ
- Spring AOP νΉμ§
- Spring AOP μ©μ΄
- Spring AOP μ€μ΅ 1
- Spring AOP μ΄λ Έν μ΄μ
- Spring AOP μ€μ΅ 2
- λ§λ¬΄λ¦¬
μ§λ ν¬μ€ν μμλ λΆκ°κΈ°λ₯μ μμνλ μ ν΅μ μΈ λ°©λ²μΌλ‘ νλ‘μ ν¨ν΄ λ° λ°μ½λ μ΄ν° ν¨ν΄μ λν΄ μ 리λ₯Ό νμμ΅λλ€.
μ΄λ² μκ°μλ λΆκ°κΈ°λ₯μ μ²λ¦¬νλ λ°©λ²μΌλ‘ Spring AOPμ κ°λ λ° μ©μ΄, μ€μ΅ λ±μ λν΄ μμλ³΄κ² μ΅λλ€.
π― Spring AOP κ°λ
AOPλ Aspect Oriented Programmingμ μ½μλ‘ κ΄μ μ§ν₯ νλ‘κ·Έλλ°μ΄λΌκ³ λ ν©λλ€.
κ΄μ μ μ½λλ₯Ό λ°λΌλ³΄λ μκ°μ λλ‘ μκ°ν΄μ£Όμλ©΄ λ κ² κ°μ΅λλ€.
κ΄μ μ§ν₯ νλ‘κ·Έλλ°μ κΈ°λ₯μ ꡬνν λ ν΅μ¬μ μΈ κΈ°λ₯κ³Ό λΆκ°μ μΈ κΈ°λ₯μ λΆλ¦¬νμ¬ κ° κ΄μ (Aspect)μ κΈ°μ€μΌλ‘ λͺ¨λνλ₯Ό νλ λ°©μμ μλ―Έν©λλ€.
- ν΅μ¬μ μΈ κΈ°λ₯: μ μ©νκ³ μ νλ λΉμ¦λμ€ λ‘μ§
- λΆκ°μ μΈ κΈ°λ₯: λ°μ΄ν°λ² μ΄μ€ μ°κ²° λ° νΈλμμ κ΄λ¦¬, λ‘κΉ , νμΌ μ μΆλ ₯ λ±
AOPμμ κ° κ΄μ μ κΈ°μ€μΌλ‘ λͺ¨λνλ₯Ό νλ€λ κ²μ μ½λλ€μ λΆλΆμ μΌλ‘ λλμ΄μ λͺ¨λνλ₯Ό νλ€λ μλ―Έμ λλ€.
μ μ¬μ§κ³Ό κ°μ΄ μ½λμμ λ€λ₯Έ λΆλΆμ λ°λ³΅μ μΌλ‘ μ¬μ©λλ μ½λλ€μ λ°κ²¬ν μ μλλ°
μ΄λ₯Ό ν‘λ¨ κ΄μ¬μ¬(Crosscutting Concerns)λΌκ³ ν©λλ€.
μ κ·Έλ¦Όμμ λͺ¨λ ν΄λμ€μ 곡ν΅μ μΌλ‘ μ¬μ©λκ³ μλ μ£Όν©μ κΈ°λ₯μ μμ ν΄μΌ νλ μΌμ΄ λ°μνλ©΄ A, B, C λͺ¨λ ν΄λμ€μμ κΈ°λ₯μ μμ ν΄μ£Όμ΄μΌ νκΈ° λλ¬Έμ μ μ§λ³΄μλ©΄μμλ ν¨μ¨μ μ΄μ§ μμ΅λλ€.
μ΄λ¬ν λ¬Έμ μ μ ν΄κ²°νκΈ° μν΄ λμ¨ κΈ°μ μ΄ AOPλ‘, μ 리ν΄λ³΄μλ©΄ λ€μκ³Ό κ°μ΅λλ€.
'ν‘λ¨ κ΄μ¬μ¬(Crosscutting Concerns)μ λΆλ¦¬λ₯Ό νμ©ν¨μΌλ‘μ¨ λͺ¨λμ±μ μ¦κ°μν€λ κ²μ΄ λͺ©μ μΈ νλ‘κ·Έλλ° ν¨λ¬λ€μ'
AOPλ κ²°κ΅ μ ν리μΌμ΄μ μ λ€μν μΈ‘λ©΄μμ λ 립μ μΌλ‘ λͺ¨λΈλ§νκ³ , μ€κ³νκ³ , κ°λ°ν μ μλλ‘ λ§λ€μ΄ μ£Όκ³ , κ·Έλ‘μΈν΄ μ ν리μΌμ΄μ μ λ€μν κ΄μ μμ λ°λΌλ³΄λ©° κ°λ°ν μ μκ² λμμ€λλ€.
μλλ μν μ ν리μΌμ΄μ μ κ΄μ¬μ¬λΌλ κ΄μ μΌλ‘ ννν ꡬ쑰μ λλ€.
μ μν μ ν리μΌμ΄μ ꡬ쑰λ κ° ν΅μ¬ κΈ°λ₯λ€(κ³μ’μ΄μ²΄, μ μΆκΈ, μ΄μκ³μ°)μ΄ μνλ λ λ§λ€ λΆκ°μ μΈ κΈ°λ₯λ€(λ‘κΉ , νΈλμμ , 보μ)μ΄ μ΄λ£¨μ΄μ ΈμΌ ν©λλ€. μ¦, κ³μ’μ΄μ²΄μ κ΄μ μμλ λ‘κΉ , νΈλμμ , 보μμ μνν΄μΌ νκ³ μ μΆκΈ, μ΄μκ³μ°μ κ΄μ μμλ λμΌνκ² λ‘κΉ , νΈλμμ , 보μ κΈ°λ₯μ μνν΄μΌ ν©λλ€.
μ ꡬ쑰μμ ν΅μ¬ κΈ°λ₯λ€μ μννλλ° λ°λμ μ€ννλ 곡ν΅μ μΈ(λΆκ°μ μΈ) κΈ°λ₯λ€μ΄ λ‘κΉ , νΈλμμ , 보μ μ λλ€. μ΄λ¬ν κ²λ€μ ν‘λ¨κ΄μ¬μ΄λΌκ³ νλλ°, μ μ΄λ¬ν λΆκ° κΈ°λ₯μ λΆλ¦¬ν΄μΌ νλκ±ΈκΉμ? λΉμ°νκ²λ, μ€λ³΅μ΄ λ°μνλ€λ λ¬Έμ μ κ³Ό μ μ§λ³΄μμ μ΄λ €μμ΄ μμ΅λλ€.
κ°λ¨ν μλμ½λ(pseudocode)λ₯Ό ν΅ν΄ λ¬Έμ μ μ λν΄ μ΄ν΄λ³΄κ² μ΅λλ€.
class λ‘κ·Έ {
static printLog();
}
class κ³μ’μ΄μ²΄ {
μ΄μ²΄() {
λ‘κ·Έ.printLog();
...
}
}
class μ
μΆκΈ {
μ
κΈ() {
λ‘κ·Έ.printLog();
...
}
}
class μ΄μκ³μ° {
μ΄μκ³μ°() {
λ‘κ·Έ.printLog();
...
}
}
μ μμ λ μ λ§ λ¨μνκ² μμ±νκΈ°λλ¬Έμ λΆνΈν¨μ λλΌμ§ λͺ»ν μλ μμ΅λλ€.
νμ§λ§ μ μμ μμ λ‘κ·Έλ₯Ό μΆλ ₯νλ printLog()μ λ©μλλͺ μ΄ λ³κ²½λμλ€λ©΄ μ΄λ»κ² ν΄μΌν κΉμ?
λ€μκ³Όκ°μ΄ λ‘κ·Έλ₯Ό μ¬μ©νκ³ μλ λͺ¨λ ν΄λμ€ λ° λ©μλλ₯Ό μ°Ύμκ° λ³κ²½ν΄μΌ νλ μΌμ΄ λ°μν©λλ€.
class λ‘κ·Έ {
static printLog4j();
}
class κ³μ’μ΄μ²΄ {
μ΄μ²΄() {
λ‘κ·Έ.printLog4j();
...
}
}
class μ
μΆκΈ {
μ
κΈ() {
λ‘κ·Έ.printLog4j();
...
}
}
class μ΄μκ³μ° {
μ΄μκ³μ°() {
λ‘κ·Έ.printLog4j();
...
}
}
νμ¬λ λ‘κ·Έ κΈ°λ₯μ μ¬μ©νκ³ μλ ν΄λμ€κ° 3κ°λ°μ μ‘΄μ¬νμ§ μμ§λ§, λ§μ½ λ‘κ·Έ κΈ°λ₯μ μ¬μ©νκ³ μλ ν΄λμ€κ° μ μ°¨ λμ΄λ 3κ°κ° μλ 30κ°, 100κ°κ° λμμλ μμ κ°μ΄ μμ μ¬νμ΄ λ°μνλ©΄ λͺ¨λ ν΄λμ€μ μ§μ μμ μ ν΄μΌνλ λ²κ±°λ‘μμ΄ λ°μν©λλ€.
λ°λΌμ μ€νλ§ AOPλ₯Ό ν΅ν΄ κ΄μ¬μ¬λ₯Ό λΆλ¦¬νκ³ μ΄λ¬ν λ¬Έμ μ μ ν΄κ²°ν΄λ³΄λλ‘ νκ² μ΅λλ€.
π― Spring AOP νΉμ§
- AOP(Aspect Oriented Programming)λ νλ‘κ·Έλ¨ κ΅¬μ‘°μ λν λ λ€λ₯Έ μ¬κ³ λ°©μμ μ 곡νμ¬ OOPλ₯Ό 보μν©λλ€.
- OOPμμ λͺ¨λνμ ν΅μ¬ λ¨μλ ν΄λμ€(μν )μ΄κ³ , AOPμμλ λͺ¨λν λ¨μκ° Aspect(κ΄μ )μ λλ€.
- Aspectλ μ¬λ¬ μ νκ³Ό κ°μ²΄μ κ±Έμ³μλ λμΌν κ΄μ¬μ¬(ex. νΈλμμ )μ λͺ¨λμ κ°λ₯νκ² ν©λλ€.
- μ€νλ§ λΉμλ§ AOPλ₯Ό μ μ©ν μ μμ΅λλ€.
π― Spring AOP μ©μ΄
AOPμμ μ¬μ©λκ³ μλ μ©μ΄λ€μ λν΄ μ΄ν΄λ³΄κ² μ΅λλ€. μλ μ©μ΄λ€μ Springμλ§ κ΅νλλ κ²μ΄ μλ AOP νλ μμν¬ μ 체μμ μ¬μ©λλ 곡μ©μ΄μ λλ€.
AOPμ μ©μ΄λ λ¨μ΄ μ체λ‘λ κ΅μ₯ν μ΄λ ΅κ³ λ¨Έλ¦¬κ° μνκΈ° λλ¬Έμ ..π.. μ λΆ μΈμ°κ³ μ΄ν΄νλ €κΈ° 보λ€λ κ°λ¨νκ² μ©μ΄μ λλ§ μ½μ΄λ³Έ ν μλ μ€μ΅μ ν΅ν΄ AOPμ λν΄ μ΄ν΄λ³΄κ³ λ€μ μ½μ΄λ³΄λ κ²μ μΆμ²λ립λλ€.
νκ²(Target)
- λΆκ°κΈ°λ₯μ λΆμ¬ν λμμ μλ―Έν©λλ€.
- μ ꡬ쑰μμλ ν΅μ¬κΈ°λ₯(κ³μ’μ΄μ²΄, μ μΆκΈ, μ΄μκ³μ°)μ λ΄μ ν΄λμ€λ₯Ό μλ―Έν©λλ€.
μ μ€ννΈ(Aspect)
- OOPμ ν΄λμ€μ λ§μ°¬κ°μ§λ‘ μ μ€ννΈλ AOPμ κΈ°λ³Έ λͺ¨λμ λλ€.
- μ μ€ννΈλ λΆκ°κΈ°λ₯μ μ μν μ΄λλ°μ΄μ€μ μ΄λλ°μ΄μ€λ₯Ό μ΄λμ μ μ©ν μ§ κ²°μ νλ ν¬μΈνΈμ»·μ μ‘°ν©μΌλ‘ ꡬμ±λ©λλ€.
- λ³΄ν΅ μ±κΈν€ ννμ μ€λΈμ νΈλ‘ μ‘΄μ¬ν©λλ€.
μ΄λλ°μ΄μ€(Advice)
- μ€μ§μ μΌλ‘ λΆκ°κΈ°λ₯μ λ΄μ ꡬν체λ₯Ό μλ―Έν©λλ€.
- μ΄λλ°μ΄μ€μ κ²½μ° νκ² μ€λΈμ νΈμ μ’ μλμ§ μκΈ° λλ¬Έμ μμνκ² λΆκ°κΈ°λ₯μλ§ μ§μ€ν μ μμ΅λλ€.
μ‘°μΈ ν¬μΈνΈ(Join Point)
- μ΄λλ°μ΄μ€κ° μ μ©λ μ μλ μμΉλ₯Ό μλ―Έν©λλ€.
- μ€νλ§ AOPμμλ λ©μλ μ‘°μΈν¬μΈνΈλ§ μ 곡νκ³ μμ΅λλ€.
- λ°λΌμ, μ€νλ§ νλ μμν¬ λ΄μμμ μ‘°μΈν¬μΈνΈλ λ©μλλ₯Ό κ°λ¦¬ν¨λ€κ³ μκ°νμ λ 무방ν©λλ€.
ν¬μΈνΈμ»·(PointCut)
- λΆκ°κΈ°λ₯μ΄ μ μ©λ λμ(λ©μλ)λ₯Ό μ μ νλ λ°©λ²μ μλ―Έν©λλ€.
- μ€νλ§ AOPμ μ‘°μΈ ν¬μΈνΈλ λ©μλμ μ€νμ΄λ―λ‘ μ€νλ§μ ν¬μΈνΈμ»·μ λ©μλλ₯Ό μ μ νλ κΈ°λ₯μ κ°κ³ μμ΅λλ€.
- λ°λΌμ ν¬μΈνΈμ»·μ ννμμ λ©μλμ μ€νμ΄λΌλ μλ―ΈμΈ executionμΌλ‘ μμνκ³ , λ©μλμ μκ·Έλμ²λ₯Ό λΉκ΅νλ λ°©λ²μ μ£Όλ‘ μ΄μ©ν©λλ€.
νλ‘μ(Proxy)
- ν΄λΌμ΄μΈνΈμ νκ² μ¬μ΄μ ν¬λͺ νκ² μ‘΄μ¬νμ¬ λΆκ°κΈ°λ₯μ μ 곡νλ μ€λΈμ νΈμ λλ€.
- DIλ₯Ό ν΅ν΄ νκ² λμ ν΄λΌμ΄μΈνΈμκ² μ£Όμ λλ©°, ν΄λΌμ΄μΈνΈμ λ©μλ νΈμΆμ λμ λ°μ νκ²μ μμν΄μ£Όλ©° λΆκ°κΈ°λ₯μ λΆμ¬ν©λλ€.
μΈνΈλ‘λμ (Introduction)
- νκ² ν΄λμ€μ μΆκ°μ μΈ λ©μλλ νλλ₯Ό μΆκ°νλ κΈ°λ₯μ μλ―Έν©λλ€.
μλΉ(Weaving)
- μ΄λλ°μ΄μ€λ₯Ό ν΅μ¬ λ‘μ§ μ½λμ μ μ©νλ κ²μ μλ―Έν©λλ€.
π― Spring AOP μ€μ΅ 1
μ€νλ§ AOPλ₯Ό μ¬μ©νκΈ° μν΄ μμ‘΄μ±μ μΆκ°ν©λλ€.
// Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
// Gradle
implementation 'org.springframework.boot:spring-boot-starter-aop'
μμ‘΄μ±μ μΆκ°ν ν μλ μ€μ΅ μ½λλ₯Ό μμ±ν©λλ€.
Controller & Dto
package com.juhyun.springaop.aop.controller;
import ...
@RestController
@RequestMapping("/api")
public class RestApiController {
@GetMapping("/{id}")
public String get(@PathVariable Long id, @RequestParam String name) {
System.out.println("--------------- @GetMapping ---------------");
// System.out.println("get method");
// System.out.println("id: " + id);
// System.out.println("name: " + name);
return id + " " + name;
}
@PostMapping
public UserDto post(@RequestBody UserDto userDto) {
System.out.println("--------------- @PostMapping ---------------");
// System.out.println("post method");
// System.out.println("user: " + user);
return userDto;
}
}
package com.juhyun.springaop.aop.dto;
import ...
@Getter
@Setter
@ToString
public class UserDto {
private String id;
private String password;
private String email;
}
AOP
package com.juhyun.springaop.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class ParameterAop {
/*
com.juhyun.springaop.aop.controller ν¨ν€μ§ νμμ μλ λ©μλκ° μ€νλκΈ° μ
-> @Before μ΄λ
Έν
μ΄μ
μ΄ μ μΈλ before() λ©μλκ° μ€ν
-> μ μ μ€νλκ³ λ¦¬ν΄λλ©΄ @AfterReturning μ΄λ
Έν
μ΄μ
μ΄ μ μΈλ afterReturn() λ©μλμμ κ²°κ³Όλ₯Ό νμΈ
*/
// controller ν¨ν€μ§μ νμ λ©μλλ₯Ό λͺ¨λ Aspectλ‘ μ€μ
@Pointcut("execution(* com.juhyun.springaop.aop.controller..*.*(..))")
private void cut() {
}
// cut() λ©μλκ° μ€νλλ μ§μ μ μ΄μ μ before() λ©μλ μν
@Before("cut()")
public void before(JoinPoint joinPoint) {
System.out.println("--------------- @Before ---------------");
System.out.println(joinPoint.toString());
System.out.println(joinPoint.toShortString());
System.out.println(joinPoint.toLongString());
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
System.out.println("method: " + method.getName());
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
System.out.println("type: " + arg.getClass().getSimpleName());
System.out.println("value: " + arg);
}
}
// λ°νκ° νμΈ
@AfterReturning(value = "cut()", returning = "object")
public void afterReturn(JoinPoint joinPoint, Object object) {
System.out.println("--------------- @After ---------------");
System.out.println(object);
}
}
νλ‘μ νΈμ ꡬ쑰λ λ€μκ³Ό κ°μ΅λλ€.
컨νΈλ‘€λ¬μ Get, Post λ©μλμ λν΄ ν μ€νΈλ₯Ό ν΄λ³΄λ©΄ λ€μκ³Ό κ°μ΅λλ€.
Controller μ½λμ λΆκ°κΈ°λ₯μΌλ‘ μ£Όμμ²λ¦¬λ System.out.println() μΆλ ₯νλ λΆλΆμ AOPλ‘ λΆλ¦¬ν¨μΌλ‘μ¨ μ»¨νΈλ‘€λ¬λ λΆκ°κΈ°λ₯(μΆλ ₯)μ ν νμκ° μμ΄ λ³ΈμΈμ κΈ°λ₯λ§ μννλ©΄ λ©λλ€.
π― Spring AOP μ΄λ Έν μ΄μ
μ μμ μμ μ¬μ©λ μ¬λ¬ μ΄λ Έν μ΄μ (@Aspect, @Component, @Pointcut, @Before, @After) λ±λ±μ λν΄ μμλ³΄κ² μ΅λλ€.
@Aspect, @Component
ν΄λΉ ν΄λμ€κ° Aspectλ₯Ό λνλ΄λ ν΄λμ€λ₯Ό λͺ μνκ³ , μ€νλ§ λΉμΌλ‘ λ±λ‘νκΈ° μν΄ @Component μ΄λ Έν μ΄μ μ λͺ μν©λλ€.
@Pointcut(ν¬μΈνΈμ»· ννμ)
ν¬μΈνΈμ»·μ μμμ λΆκ°κΈ°λ₯μ΄ μ μ©λ λμ(λ©μλ)λ₯Ό μ μ νλ λ°©λ²μ΄λΌκ³ μ€λͺ μ λλ Έμλλ°μ, ν¬μΈνΈμ»· ννμμ λ¬Έλ²κ΅¬μ‘°λ λ€μκ³Ό κ°μ΅λλ€.
[] κ΄νΈλ μ΅μ μ΄κΈ° λλ¬Έμ μλ΅μ΄ κ°λ₯νλ©°, | λ OR 쑰건μ λλ€.
μ μμ μμ μμ±ν ν¬μΈνΈμ»·μ λ€μκ³Ό κ°μ΅λλ€.
// controller ν¨ν€μ§μ νμ λ©μλλ₯Ό λͺ¨λ Aspectλ‘ μ€μ
@Pointcut("execution(* com.juhyun.springaop.aop.controller..*.*(..))")
μ λ¬Έλ²μ ν΄μν΄λ³΄μλ©΄ λ€μκ³Ό κ°μ΅λλ€.
- execution: ν¬μΈνΈμ»· μ§μ μ
- *: λͺ¨λ νμ μ 리ν΄μ΄ κ°λ₯
- com.~.controller..*.*: (νκ²μ΄ λλ λ©μλ) ν΄λΉ ν¨ν€μ§ νμμ μ‘΄μ¬νλ λͺ¨λ λ©μλλ€
- (..): λͺ¨λ νμ μ νλΌλ―Έν°μ λν΄ νμ©νλ 쑰건
λ§μ½ μ μμ μμ RestApiController ν΄λμ€ νμμ μ‘΄μ¬νλ get() λ©μλλ§ μ€μ νλ €κ³ νλ©΄ λ€μκ³Ό κ°μ΄ μ§μ νλ©΄ λ©λλ€.
// RestApiController ν΄λμ€ νμμ get λ©μλλ₯Ό Aspectλ‘ μ§μ
@Pointcut("execution(* com.juhyun.springaop.aop.controller.RestApiController.get(..))")
ν μ€νΈλ₯Ό ν΄λ³΄λ©΄ get λ©μλμλ λ¬λ¦¬ post λ©μλμλ AOP μ μ©μ΄ λμ§μμ κ±Έ νμΈν μ μμ΅λλ€.
ν¬μΈνΈμ»· ννμ μμ
- execution(int minus(int, int)): int νμ μ λ¦¬ν΄ κ°, minusλΌλ λ©μλ, λ κ°μ int νλΌλ―Έν°λ₯Ό κ°μ§λ λ©μλ
- execution(* minus(int, int)): λͺ¨λ νμ μ 리ν΄, minusλΌλ λ©μλ, λ κ°μ int νλΌλ―Έν°λ₯Ό κ°μ§λ λ©μλ
- execution(* minus(..)): λ¦¬ν΄ νμ , νλΌλ―Έν° μ’ λ₯, κ°μμ μκ΄μμ΄ minusλΌλ λ©μλ μ΄λ¦μ κ°μ§ λͺ¨λ λ©μλ
- execution(* minus()): λ¦¬ν΄ νμ μ μκ΄μμ΄ νλΌλ―Έν°κ° μ‘΄μ¬νμ§ μλ minus λ©μλ
- execution(* *(..)): λ¦¬ν΄ νμ , νλΌλ―Έν°, λ©μλ μ΄λ¦μ μκ΄μμ΄ λͺ¨λ 쑰건μ νμ©νλ ν¬μΈνΈμ»· ννμ
- execution(* com.juhyun.aop.Target.*(..)): com.juhyun.aop ν¨ν€μ§μ Target ν΄λμ€μ μ‘΄μ¬νλ λ©μλ
- execution(* com.juhyun.aop.*.*(..)): com.juhyun.aop ν¨ν€μ§μ μ‘΄μ¬νλ λͺ¨λ ν΄λμ€
@Before
νκ² λ©μλκ° μ€ννκΈ° μ΄μ μ΄λλ°μ΄μ€ κΈ°λ₯μ μν
@After
νκ² λ©λμ€μ κ²°κ³Όμ μκ΄μμ΄ μ€ν ν μ΄λλ°μ΄μ€ κΈ°λ₯μ μν
@AfterReturning
νκ² λ©μλκ° μ μμ μΌλ‘ κ²°κ³Όκ°μ λ°ν ν μ΄λλ°μ΄μ€ κΈ°λ₯μ μν
@AfterThrowing
νκ² λ©μλκ° μν μ€ μμΈλ₯Ό λ°μνλ©΄ μ΄λλ°μ΄μ€ κΈ°λ₯μ μν
@Around
μ΄λλ°μ΄μ€κ° νκ² λ©μλλ₯Ό κ°μΈμ νκ² λ©μλ νΈμΆμ , ν μ΄λλ°μ΄μ€ κΈ°λ₯μ μν
Aroundλ νκ²μ μ€νν μ§ νΉμ λ°λ‘ λ°νν μ§λ μ ν μ μμ
π― Spring AOP μ€μ΅ 2
μ΄λ² μ€μ΅μμλ νΉμ λ©μλμ μκ°μ κΈ°λ‘νλ λΆκ°κΈ°λ₯μ AOPλ₯Ό ν΅ν΄ μ μ©ν΄λ³΄λλ‘ νκ² μ΅λλ€.
νλ‘μ νΈ κ΅¬μ‘° λ° μ λ°μ μΈ μ½λλ μ μ€μ΅ 1κ³Ό λμΌν©λλ€.
// 컀μ€ν
μ΄λ
Έν
μ΄μ
package com.juhyun.springaop.aop.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Timer {
}
// RestApiController
... μλ΅
@Timer
@DeleteMapping("/delete")
public String delete() throws InterruptedException {
// DB logic 2μ΄ μν
Thread.sleep(1000 * 2);
return "delete";
}
// AOP
package com.juhyun.springaop.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
@Aspect
@Component
public class TimerAop {
@Pointcut("execution(* com.juhyun.springaop.aop.controller..*.*(..))")
private void cut() { }
@Pointcut("@annotation(com.juhyun.springaop.aop.annotation.Timer)")
private void enableTimer() { }
@Around("cut() && enableTimer()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("--------------- @Around ---------------");
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// νκ² μ€λΈμ νΈμ λ©μλ μ€ν(controller ν¨ν€μ§ νμ ν΄λμ€λ€μ λ©μλ)
Object result = joinPoint.proceed();
System.out.println("result: " + result);
stopWatch.stop();
System.out.println("Total Time: " + stopWatch.getTotalTimeSeconds());
}
}
μ μμ μμλ ProceddingJoinPoint λΌλ ν΄λμ€κ° μΆκ°λμλλ°μ, ν΄λΉ ν΄λμ€μ proceed()λ©μλλ₯Ό μ€νν¨μΌλ‘μ νκ² μ€λΈμ νΈμ λ©μλκ° μ€νμ΄ λ©λλ€. λ°λΌμ ν΄λΉ μ½λ μ νλ‘ λΆκ°κΈ°λ₯μ μν μ½λλ₯Ό μμ±νλ©΄ λ©λλ€.
β» μ£Όμνμ€ μ μ @Around μ΄λλ°μ΄μ€μμλ§ ProceedingJoinPoint λ₯Ό 맀κ°λ³μλ‘ μ¬μ©νκ³ , λλ¨Έμ§ @Before, @After, @AfterReturning, @AfterThrowing μ΄λλ°μ΄μ€μμλ JoinPointλ₯Ό 맀κ°λ³μλ‘ μ¬μ©ν©λλ€. μ΄λ Around μ΄λλ°μ΄μ€μμλ§ proceed() λ©μλκ° νμνκΈ° λλ¬Έμ λλ€.
λν TimerλΌλ μ΄λ Έν μ΄μ κΈ°λ°μΌλ‘ μμ λ₯Ό μμ±νμ΅λλ€. ν΄λΉ μ΄λ Έν μ΄μ μ μ¬μ©ν λ©μλ(delete)μ μ μ©νκ³ , AOPμμλ μ΄λ₯Ό μ μ©νκΈ° μν΄ μ μ© λ²μλ₯Ό μ€μ νλ cut() λ©μλμ, Timer μ΄λ Έν μ΄μ μ μ€μ νλ enableTimer() λ©μλλ₯Ό μμ±ν©λλ€.
μ€ν μκ°μ νκ² λ©μλ(delete)μ μ , ν μ μ΄λ£¨μ΄μ ΈμΌ νκΈ° λλ¬Έμ @Around μ΄λ Έν μ΄μ μ ν΅ν΄ μ€μ ν©λλ€.
around() λ©μλμμλ joinPoint.proceed() μ½λλ₯Ό κΈ°λ°μΌλ‘ μμλ μ€ν μ , μλλ μ€ν ν μννκ² λ©λλ€.
π― λ§λ¬΄λ¦¬
μ΄μμΌλ‘ μ€νλ§ AOPμ νλ‘μ ν¨ν΄, λ°μ½λ μ΄ν° ν¨ν΄μ λν΄ μ 리νκ³ νμ΅ν΄λ³΄μμ΅λλ€.
κ°μΈμ μΌλ‘ AOPμ κ²½μ° Target, Aspect, Advice, PointCut, Join Point λ±λ± μ©μ΄λ§ λ΄€μλλ μ΄ν΄κ° μ ~ν λμ§μμμ΅λλ€.
νμ§λ§ μ΄λ² ν¬μ€ν μ κ³κΈ°λ‘ μ¬λ¬ μλ£μ λ¬Έμ, μμ λ±μ μ°Έκ³ νλ©° AOPμ λν΄ μ 리λ₯Ό ν΄λ³΄μμ΅λλ€. νμ€ν μ΄λ‘ 보λ€λ μ€μ΅μ ν΅ν΄ νμ΅νλ κ²μ΄ μ΄ν΄νκΈ°μλ ν¨μ¬ λ μμν κ² κ°μ΅λλ€.π
λ¬Όλ‘ μ κ° νμ΅ν λ΄μ©μ μ§κ·Ήν μΌλΆμ΄μ§λ§, λ€μμ AOPλ₯Ό μ€λ¬΄μμ νΉμ κ°μΈμ μΌλ‘ μ¬μ©ν΄ λ³Ό κΈ°νκ° μκΈ΄λ€λ©΄ κ·Έλ μ’ λ μΆκ°μ μΌλ‘ μ 리ν΄λ³΄λλ‘ νκ² μ΅λλ€.
References
- https://jojoldu.tistory.com/71
- https://fastcampus.co.kr/
- https://docs.spring.io/spring-framework/docs/2.5.x/reference/aop.html
- ν λΉμ μ€νλ§ 3.1
'Spring' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Spring Data MongoDB Array field $elemMatch(MongoRepository Custom) (2) | 2022.08.20 |
---|---|
Spring Boot SQL μ€μ (hibernate, logging) (4) | 2022.03.12 |
[Spring] - λ‘κΉ : Log4j, Log4j2, Slf4j, Logback (0) | 2021.09.15 |
Spring Validation - @NotNull, @NotEmpty, @NotBlank (0) | 2021.09.09 |
Spring Boot + MockMvc ν μ€νΈ(feat. Kotlin) (0) | 2021.09.07 |
λκΈ