[Spring] AOP(Aspect Oriented Programming) ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ
๐AOP๋?
AOP๋ Aspect Oriented Programming์ ์ฝ์๋ก ๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ํ๋ค.
๊ด์ ์งํฅ์ ์ฝ๊ฒ ๋งํด ์ด๋ค ๋ก์ง์ ๊ธฐ์ค์ผ๋ก ํต์ฌ์ ์ธ ๊ด์ , ๋ถ๊ฐ์ ์ธ ๊ด์ ์ผ๋ก ๋๋์ด์ ๋ณด๊ณ
๊ทธ ๊ด์ ์ ๊ธฐ์ค์ผ๋ก ๊ฐ๊ฐ ๋ชจ๋ํํ๊ฒ ๋ค๋ ๊ฒ
์ด๋, ๋ชจ๋ํ๋ ์ด๋ค ๊ณตํต๋ ๋ก์ง์ด๋ ๊ธฐ๋ฅ์ ํ๋์ ๋จ์๋ก ๋ฌถ๋ ๊ฒ์ ๋งํ๋ค.
๐AOP ๊ด๋ จ ์ฉ์ด
Aspect
ํฉ์ด์ง ๊ด์ฌ์ฌ๋ฅผ ๋ชจ๋ํํ์ฌ ํ๋๋ก ๋ฌถ๋ ๊ฒ, ์ผ๋ฐ์ ์ผ๋ก ๋ถ๊ฐ๊ธฐ๋ฅ์ ๋ชจ๋ํ.
Target ; Aspect์ ์ ์ฉํ๋ ๊ณณ
Aspect๋ฅผ ์ ์ฉํ๋ ๊ณณ (ํด๋์ค, ๋ฉ์๋ ๋ฑ)
Advice ; ์ฐ๋ฆฌ๊ฐ ๊ฐ๋ฐํด์ผํ๋ ๊ฒ
์ค์ง์ ์ผ๋ก ์ด๋ค ์ผ์ ํด์ผํ ์ง์ ๋ํด ์ ์ํ ๊ฒ, ์ค์ง์ ์ธ ๋ถ๊ฐ๊ธฐ๋ฅ์ ๊ตฌํํ ๊ตฌํ์ฒด
JointPoint ; ์ด๋ค ์์ ์ ์ ์ฉ์ํฌ์ง. ์์ !
๋ฉ์๋ ์ง์ ์ง์ , ์์ฑ์ ํธ์ถ ์์ , ํ๋์์ ๊ฐ์ ๊บผ๋ด์ฌ ๋ ๋ฑ๊ณผ ๊ฐ์ด Advice๊ฐ ์ ์ฉ๋ ์์น, ๋ผ์ด๋ค ์ ์๋ ์ง์ .
PointCut; ์ ์ฉํ ๋ถ๋ถ
JointPoint์ ์์ธํ ์คํ์ ์ ์ํ ๊ฒ.
๐๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
pom.xml
<!--AOP-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
๐AOP ์ฌ์ฉ ์์
SimpleAop.java
package com.example.demo.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;
//AOP๊ฐ ์ ์ฉ๋๋ ๊ณณ์ ์คํ๋ง์ ๋น์ผ๋ก ๋ฑ๋ก๋๋ ์ ๋ค์ด๋ค.
//๋ฐ๋ผ์ ์ด ํด๋์ค๋ @Component๋ฅผ ํตํด ๋น์ ๋ฌ์์ค์ผ ํ๋ค.
//๊ด์ ์ด๋ค ๋ผ๋ ์ง์ ์ @Aspect ์ด๋
ธํ
์ด์
์ผ๋ก ํ๋ค.
@Component
@Aspect
public class SimpleAop {
//Pointcut์ผ๋ก ์ ์ฉํ ๋ถ๋ถ์ ์ง์ ํด์ค
//member ํจํค์ง ์๋ ๋ชจ๋ ํ์ผ๋ค์ ์ง์
@Pointcut("execution(* com.example.demo.member..*.*(..))")
private void cut(){
System.out.println("์ปท");
}
//๋ฉ์๋๊ฐ ์คํ๋๊ธฐ ์ ์ ์ง์
@Before("cut()")
public void before(JoinPoint joinPoint){
Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
System.out.println(method.getName() + "๋ฉ์๋ ์คํ ์ ");
}
//๋ฉ์๋ ์คํ ํ
//๋ฉ์๋ ์ง์ , ๋ฐํ ๊ฐ ์ง์
@AfterReturning(value = "cut()", returning = "returnObject")
public void afterReturning(JoinPoint joinPoint, Object returnObject) {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
System.out.println(returnObject.getClass().getName() + "๋ฐํ ");
System.out.println(method.getName() + "๋ฉ์๋ ์คํ ํ ");
}
}
@PointCut:
์ ์ฉ๋ ๋ถ๋ถ์ ์ง์
@Before:
๋ฉ์๋๊ฐ ์คํ๋๊ธฐ ์ ์์ ์์ ์ฒ๋ฆฌ
@AfterReturning:
๋ฉ์๋ ์คํ ํ ์์ ์์ ์ฒ๋ฆฌ
== ์์ ์ค์ต์ ์ํ Model, Controller, Service, Repository ==
[Model] Member.java
package com.example.demo.member.model;
import lombok.*;
import javax.persistence.*;
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Builder
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
@Column(unique = true, nullable = false)
String email;
String password;
}
[Controller] MemberController.java
package com.example.demo.member.controller;
import com.example.demo.member.service.MemberService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/member")
public class MemberController {
private final MemberService memberService;
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
@RequestMapping(method = RequestMethod.POST, value = "/login")
public ResponseEntity login(){
memberService.loginService();
return ResponseEntity.ok().body("login process");
}
@RequestMapping(method = RequestMethod.POST, value = "/signup")
public ResponseEntity signup(String email, String password){
memberService.signupService(email, password);
return ResponseEntity.ok().body("signup process");
}
}
[Service] MemberService.java
package com.example.demo.member.service;
import com.example.demo.member.model.Member;
import com.example.demo.member.repository.MemberRepository;
import org.springframework.stereotype.Service;
@Service
public class MemberService {
MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
public void signupService(String email, String password) {
memberRepository.save(Member.builder()
.email(email)
.password(password)
.build());
}
public void loginService() {
System.out.println("๋ฉค๋ฒ ์๋น์ค์ ๋ก๊ทธ์ธ ๋ฉ์๋ ์คํ");
}
}
[Repository] MemberRepository.java
package com.example.demo.member.repository;
import com.example.demo.member.model.Member;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface MemberRepository extends JpaRepository<Member, Integer> {
public Optional<Member> findByEmail(String email);
}
๐์คํ ๊ฒฐ๊ณผ
์ ์ฝ๋๋ฅผ ์คํํ๊ณ , signup์ ์คํํ๋ฉด ๋ก๊ทธ์ ๋ค์๊ณผ ๊ฐ์ด ๋ฌ๋ค.
@Before์์ ๋ฉ์๋ ์คํ ์ ์ ์ถ๋ ฅํ๊ฒ ํ ๊ฒ๋ ์ ์คํ๋ ๊ฑธ ํ์ธ ํ ์ ์๋ค.
Hibernate์ผ๋ก database์ insert๊ฐ ๋๊ณ ๋ฉ์๋๊ฐ ๋๋ ํ์ @AfterReturning์์ ์ฒ๋ฆฌํ ๋ฉ์๋ ์คํ ํ ๋ํ ์ ์ถ๋ ฅ๋๋ค.
signup ์์ฒญ์ postman์ ์ด์ฉํด์ ๋ณด๋ด์ฃผ์๊ณ , ์ค๋ฅธ์ชฝ ๊ทธ๋ฆผ์์ database์๋ ์ ๋ค์ด๊ฐ๋ค.