μΆμ² : λ΄μΌλ°°μμΊ ν
Aspect Oriented Programming : κ΄μ μ§ν₯ νλ‘κ·Έλλ°
- AOP κ°λ μ΄ν΄
- 'λλ§μ μ
λ μ΅' μ μ€νλ§ AOP μ μ©
- Top5 νμ μ°ΎκΈ°
- μ€λ³΅ ν΄λλͺ μ μ₯ μ μλ¬ μ²λ¦¬
- μ€νλ§ μμΈ μ²λ¦¬
μλ²λ₯Ό μ¬μ©ν μκ° ~ λͺ¨λ APIμ μμ², μλ΅ν μκ°μ ν©μ κΈ°μ€μΌλ‘ μμ 5μΈ μ λ°
μ€ν¬λμΉ νμΌμ μ΄μ©ν μλ² μ¬μ©μκ° μΈ‘μ
+ μ€ν¬λμΉ νμΌμ λ³λλ‘ μ μ₯λλ μμνμΌ, νλ‘μ νΈμ κ΄λ ¨μλ μ½λλ₯Ό λ€λ£° λ μ μ©νλ€
class Scratch {
public static void main(String[] args) {
// μΈ‘μ μμ μκ°
long startTime = System.currentTimeMillis();
// ν¨μ μν
long output = sumFromOneTo(1_000_000_000);
// μΈ‘μ μ’
λ£ μκ°
long endTime = System.currentTimeMillis();
long runTime = endTime - startTime;
System.out.println("μμμκ°: " + runTime);
}
private static long sumFromOneTo(long input) {
long output = 0;
for (int i = 1; i < input; ++i) {
output = output + i;
}
return output;
}
}
outputμ κ°μ μ΄κΈ°κ° 1μ΄λ‘ μ€μ ν ν, μ¬μ©μκ°λ§νΌ κ°μ μ¦κ°μν€λ λ°λ³΅λ¬Έμ ν΅ν΄ μκ°μ ν©μ ꡬνλ€
TOP 5 νμ μ°ΎκΈ° μ€κ³ λ° κ΅¬ν
컬λΌλͺ | νμ | μ€λ³΅νμ© | μ€λͺ |
id | Long | X | ν μ΄λΈ ID(PK) |
userId | Long | X | νμ ID(FK) |
totalTime | Long | O | API μ΄ μ¬μ©μκ° |
ApiUseTime μμ±
ApiUseTimeRepository μμ±
ProductController μ¬μ©μκ° κΈ°λ‘ μΆκ°
(κ΄λ¦¬μ) νμλ³ API μ΄ μ¬μ©μκ° μ‘°ν API μ€κ³ λ° κ΅¬ν
κΈ°λ₯ | λ©μλ | URL | μ€λͺ |
API μ΄ μ¬μ©μκ° μ‘°ν | GET | /api/use/time | νμλ³ API μ΄ μ¬μ©μκ° μ‘°ν (κ΄λ¦¬μμ©) |
ApiUseTimeController μμ±
AOPλ?
κ° API λ³ μνν΄μΌ νλ μ£Όμ λΉμ¦λμ€ λ‘μ§μ μ μΈν λΆκ°κΈ°λ₯μ λͺ¨λννμ¬ λΆκ°κΈ°λ₯ μ€μ¬μΌλ‘ μ€κ³ ꡬννλ κ²
~ μ€νλ§μ΄ μ 곡νλ AOP
AOPλ₯Ό μ¬μ©ν΄ λͺ¨λ 컨νΈλ‘€λ¬μ λΆκ°κΈ°λ₯ μΆκ°
package com.sparta.myselectshop.aop;
import com.sparta.myselectshop.entity.ApiUseTime;
import com.sparta.myselectshop.entity.User;
import com.sparta.myselectshop.repository.ApiUseTimeRepository;
import com.sparta.myselectshop.security.UserDetailsImpl;
import lombok.RequiredArgsConstructor;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class UseTimeAop {
private final ApiUseTimeRepository apiUseTimeRepository;
@Around("execution(public * com.sparta.myselectshop.controller..*(..))")
public synchronized Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
// μΈ‘μ μμ μκ°
long startTime = System.currentTimeMillis();
try {
// ν΅μ¬κΈ°λ₯ μν
Object output = joinPoint.proceed();
return output;
} finally {
// μΈ‘μ μ’
λ£ μκ°
long endTime = System.currentTimeMillis();
// μνμκ° = μ’
λ£ μκ° - μμ μκ°
long runTime = endTime - startTime;
// λ‘κ·ΈμΈ νμμ΄ μλ κ²½μ°, μνμκ° κΈ°λ‘νμ§ μμ
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getPrincipal().getClass() == UserDetailsImpl.class) {
// λ‘κ·ΈμΈ νμ μ 보
UserDetailsImpl userDetails = (UserDetailsImpl) auth.getPrincipal();
User loginUser = userDetails.getUser();
// API μ¬μ©μκ° λ° DB μ κΈ°λ‘
ApiUseTime apiUseTime = apiUseTimeRepository.findByUser(loginUser)
.orElse(null);
if (apiUseTime == null) {
// λ‘κ·ΈμΈ νμμ κΈ°λ‘μ΄ μμΌλ©΄
apiUseTime = new ApiUseTime(loginUser, runTime);
} else {
// λ‘κ·ΈμΈ νμμ κΈ°λ‘μ΄ μ΄λ―Έ μμΌλ©΄
apiUseTime.addUseTime(runTime);
}
log.info("[API Use Time] Username: " + loginUser.getUsername() + ", Total Time: " + apiUseTime.getTotalTime() + " ms");
apiUseTimeRepository.save(apiUseTime);
}
}
}
}
AOP μ μ© μ
AOP μ μ© ν
μ€νλ§ AOP μ΄λ Έν μ΄μ μ μ’ λ₯
1. @Aspect
μ€νλ§ λΉ ν΄λμ€μ μ μ©κ°λ₯
2. μ΄λλ°μ΄μ€μ μ’ λ₯ ~ AOP μ½λκ° μ€νλλ μμ μ μ§μ ν΄μ€λ€
- @Around : 'ν΅μ¬κΈ°λ₯' μν μ κ³Ό ν(@Before + @After)
- @Before : 'ν΅μ¬κΈ°λ₯' μν μ (ex : Clientμ μ λ ₯κ° Vaildation μν)
- @After : 'ν΅μ¬κΈ°λ₯' μν μ±κ³΅/μ€ν¨ μ¬λΆμ κ΄κ³μμ΄ μΈμ λ λμ (try, catchμ finally()μ κ°μ λμ λ°©μ)
- @AfterReturning : 'ν΅μ¬κΈ°λ₯' νΈμΆ μ±κ³΅μ λμνμ¬ ν¨μμ Returnκ° μ¬μ©κ°λ₯
- @AfterThrowing : 'ν΅μ¬κΈ°λ₯' νΈμΆ μ€ν¨μ, μμΈκ° λ°μν κ²½μ°μλ§ λμ (ex : μμΈλ°μμ κ°λ°μμκ² ν΅μ§κΈ°λ₯)
3. ν¬μΈνΈμ»· ~ AOP μ½λκ° μ€νλλ μ₯μλ₯Ό μ ν΄μ€λ€
μμ -> @μ΄λλ°μ΄μ€(ν¬μΈνΈμ»·)μ νν
execution(
modifiers-pattern?
return-type-pattern declaring-type-pattern?
method-name-pattern(param-pattern) throws-pattern?)β
@Around("execution(public * com.sparta.springcore.controller..*(..))")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable { ... }
modifiers-pattern : pubilc, private, *
return-type-pattern : void, String, List<String>, *
declaring-type-pattern : ν΄λμ€λͺ (ν¨ν€μ§λͺ νμ)
~ com.sparta.springcore.controller.* : controller ν¨ν€μ§μ λͺ¨λ ν΄λμ€μ μ μ©
~ com.sparta.springcore.controller.. : controller ν¨ν€μ§ λ° νμ ν¨ν€μ§μ λͺ¨λ ν΄λμ€κΉμ§ μ μ©
method-name-pattern(param-pattern)
ν¨μλͺ
addFolders : addFolders() ν¨μμλ§ μ μ©
add* : addλ‘ μμνλ λͺ¨λ ν¨μμ μ μ©
νλΌλ―Έν° ν¨ν΄
(com.sparta.springcore.dto.FolderRequestDto) - FolderRequestDto μΈμμλ§ μ μ©
() - μΈμ μμ
(*) - νμ μκ΄μμ΄ μΈμ 1κ°
(..) - νμ μκ΄μμ΄ μΈμ 1~Nκ°
'Springπ' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Spring Transaction (0) | 2022.12.29 |
---|---|
Spring Exception (0) | 2022.12.29 |
ν μ€νΈ μ½λ (0) | 2022.12.27 |
OAuth2 (0) | 2022.12.27 |
μ€νλ§ μλ ¨ : Project MySelectShop (3) (0) | 2022.12.15 |