[스프링 입문] 스프링 예제 프로젝트 PetClinic 3
스프링 AOP
Aspect Oriented Programming
다양한 AOP
- 구현 방법 3가지
- 컴파일
- A.java —-AOP—-> A.class (제공 : AspectJ)
- : 자바코드에는 없지만 컴파일을 한 코드에는 있는 것처럼 컴파일 해주는!
- 바이트코드 조작
- A.java → A.class ——AOP(위치 : 클래스 로더)——> 메모리 (제공 : AspectJ)
- 프록시 패턴
- 스프링 AOP, 디자인 패턴을 사용해서 AOP와 같은 효과를 내는 방법. (참고 : https://refactoring.guru/design-patterns/proxy)
프록시 패턴
-
기존 코드 건드리지 않고 새 기능 추가하기
-
프록시 패턴
-
Main에서의 클래스
-
main\java\org...\proxy\Store
package org.springframework.samples.petclinic.proxy;
public class Store {
Payment payment;
public Store(Payment payment) {
this.payment = payment;
}
public void buySomething(){
payment.pay(100);
}
}
-
main\java\org...\proxy\Cash
package org.springframework.samples.petclinic.proxy;
public class Cash implements Payment{
@Override
public void pay(int amount) {
System.out.println(amount + " 현금 결제");
}
}
-
main\java\org...\proxy\Payment
package org.springframework.samples.petclinic.proxy;
public interface Payment {
void pay(int amount);
}
-
main\java\org...\proxy\CashPerf
package org.springframework.samples.petclinic.proxy;
import org.springframework.util.StopWatch;
public class CashPerf implements Payment {
Payment cash = new Cash();
@Override
public void pay(int amount) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
cash.pay(amount);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
}
} //일종의 프록시
-
Test 확인
-
test\java\org...\proxy\StoreTest
package org.springframework.samples.petclinic.proxy;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class StoreTest {
@Test
public void testPay(){
//Payment cashPerf = new Cash(); //(1)
Payment cashPerf = new CashPerf(); **//(2)**
Store store = new Store(cashPerf);
store.buySomething(100);
}
}
-
(1)
-
(2) - 프록시 클래스를 사용하도록 함.
-
원래는 Cash가 Bean으로 등록이 되어야 하는데 내가 만들고 싶은 CashPerf(proxy)가 자동으로 생겨서 Cash 대신에 등록이 되고 Client가 CashPerf를 대신 쓰게 되는 일이 Spring 내부에서 발생한다.
-
스프링 AOP 기반의 @Transactional
이 위와 같은 일을 한다.
스프링 @AOP 실습
-
@LogExecutionTime
설정(어디에 적용할지)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
}
//위치 : java\org..\owner\LogExecutionTime
@Target
: 어디에 쓸 수 있는지.
@Retension
: @
정보를 언제까지 유지할 것인가.
-
java\org..\owner\LogAspect
: 스프링 AOP(프록시 패턴 기반)
Proxy 패턴(스프링 AOP)
@Component
@Aspect
public class LogAspect {
Logger logger = LoggerFactory.getLogger(LogAspect.class);
**@Around("@annotation(LogExecutionTime)")**
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object proceed = joinPoint.proceed();
stopWatch.stop();
logger.info(stopWatch.prettyPrint());
return proceed;
}
}
- joinPoint 파라미터 =
@LogExecutionTime
이 붙은 메소드(타겟)
@Around("@annotaion(LogExecutionTime)")
: LogExecutionTime이라는 @
주변에 적용하겠다.
@Around
외에도 @After
, @Before
등.
@annotation
외에도 @Bean
, Method들이 진행되는 시점 등.
-
java\org..\owner\OwnerController
에서 성능(시간)을 측정할 메소드 위에 @LogExecutionTime
을 추가하자.
Target(타겟)
@GetMapping("/owners/new")
@LogExecutionTime
public String initCreationForm(Map<String, Object> model) {
Owner owner = new Owner();
model.put("owner", owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/owners/new")
@LogExecutionTime
public String processCreationForm(@Valid Owner owner, BindingResult result) {
if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
else {
this.owners.save(owner);
return "redirect:/owners/" + owner.getId();
}
}
@GetMapping("/owners/find")
@LogExecutionTime
public String initFindForm(Map<String, Object> model) {
model.put("owner", new Owner());
return "owners/findOwners";
}
- 앱을 실행하고
@LogExecutionTime
이 명시된 메소드들이 실행될 때 각 메소드들이 실행되는 시간, 즉 성능을 Runtime으로 표시한다.
Author And Source
이 문제에 관하여([스프링 입문] 스프링 예제 프로젝트 PetClinic 3), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@jinmin2216/스프링-입문-스프링-예제-프로젝트-PetClinic-3
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Aspect Oriented Programming
- 컴파일
- A.java —-AOP—-> A.class (제공 : AspectJ)
- : 자바코드에는 없지만 컴파일을 한 코드에는 있는 것처럼 컴파일 해주는!
- 바이트코드 조작
- A.java → A.class ——AOP(위치 : 클래스 로더)——> 메모리 (제공 : AspectJ)
- 프록시 패턴
- 스프링 AOP, 디자인 패턴을 사용해서 AOP와 같은 효과를 내는 방법. (참고 : https://refactoring.guru/design-patterns/proxy)
기존 코드 건드리지 않고 새 기능 추가하기
프록시 패턴
Main에서의 클래스
-
main\java\org...\proxy\Store
package org.springframework.samples.petclinic.proxy; public class Store { Payment payment; public Store(Payment payment) { this.payment = payment; } public void buySomething(){ payment.pay(100); } }
-
main\java\org...\proxy\Cash
package org.springframework.samples.petclinic.proxy; public class Cash implements Payment{ @Override public void pay(int amount) { System.out.println(amount + " 현금 결제"); } }
-
main\java\org...\proxy\Payment
package org.springframework.samples.petclinic.proxy; public interface Payment { void pay(int amount); }
-
main\java\org...\proxy\CashPerf
package org.springframework.samples.petclinic.proxy; import org.springframework.util.StopWatch; public class CashPerf implements Payment { Payment cash = new Cash(); @Override public void pay(int amount) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); cash.pay(amount); stopWatch.stop(); System.out.println(stopWatch.prettyPrint()); } } //일종의 프록시
Test 확인
-
test\java\org...\proxy\StoreTest
package org.springframework.samples.petclinic.proxy; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class StoreTest { @Test public void testPay(){ //Payment cashPerf = new Cash(); //(1) Payment cashPerf = new CashPerf(); **//(2)** Store store = new Store(cashPerf); store.buySomething(100); } }
-
(1)
-
(2) - 프록시 클래스를 사용하도록 함.
원래는 Cash가 Bean으로 등록이 되어야 하는데 내가 만들고 싶은 CashPerf(proxy)가 자동으로 생겨서 Cash 대신에 등록이 되고 Client가 CashPerf를 대신 쓰게 되는 일이 Spring 내부에서 발생한다.
스프링 AOP 기반의 @Transactional
이 위와 같은 일을 한다.
@LogExecutionTime
설정(어디에 적용할지)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
}
//위치 : java\org..\owner\LogExecutionTime
@Target
: 어디에 쓸 수 있는지.@Retension
:@
정보를 언제까지 유지할 것인가.
java\org..\owner\LogAspect
: 스프링 AOP(프록시 패턴 기반)
Proxy 패턴(스프링 AOP)
@Component
@Aspect
public class LogAspect {
Logger logger = LoggerFactory.getLogger(LogAspect.class);
**@Around("@annotation(LogExecutionTime)")**
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object proceed = joinPoint.proceed();
stopWatch.stop();
logger.info(stopWatch.prettyPrint());
return proceed;
}
}
- joinPoint 파라미터 =
@LogExecutionTime
이 붙은 메소드(타겟) @Around("@annotaion(LogExecutionTime)")
: LogExecutionTime이라는@
주변에 적용하겠다.@Around
외에도@After
,@Before
등.@annotation
외에도@Bean
, Method들이 진행되는 시점 등.
java\org..\owner\OwnerController
에서 성능(시간)을 측정할 메소드 위에 @LogExecutionTime
을 추가하자.
Target(타겟)
@GetMapping("/owners/new")
@LogExecutionTime
public String initCreationForm(Map<String, Object> model) {
Owner owner = new Owner();
model.put("owner", owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/owners/new")
@LogExecutionTime
public String processCreationForm(@Valid Owner owner, BindingResult result) {
if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
else {
this.owners.save(owner);
return "redirect:/owners/" + owner.getId();
}
}
@GetMapping("/owners/find")
@LogExecutionTime
public String initFindForm(Map<String, Object> model) {
model.put("owner", new Owner());
return "owners/findOwners";
}
- 앱을 실행하고
@LogExecutionTime
이 명시된 메소드들이 실행될 때 각 메소드들이 실행되는 시간, 즉 성능을 Runtime으로 표시한다.
Author And Source
이 문제에 관하여([스프링 입문] 스프링 예제 프로젝트 PetClinic 3), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jinmin2216/스프링-입문-스프링-예제-프로젝트-PetClinic-3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)