728x90
[AOP 목표]
- 기존 코드 수정 없이 원하는 관심사들을 엮어서 전체 구현 쉽게 하기
즉, 개발자들이 핵심 로직 코드만 개발하고 나머지 코드 부분은 어떤 관심사들과 결합할지 설정 만으로 전체 기능 효율적 개발 추구
[AOP 개념]
- AOP : 핵심 기능/주변 기능 분리하여 코드 작성해놓고, 실행 시점에 결합하는 방식
핵심로직과 주변로직의 분리를 추구 = 관심사의 분리
핵심 비즈니스 로직과 부가기능(=공통기능) 코드의 분리 추구
ex. 입력 값에 대한 나눗셈 기능 구현 시, 1) 입력 값이 0 이상의 양수인지 확인한는 기능 : 관심사(주변 로직) 2) 실질적인 입력값 간의 나눗셈 기능 : 비즈니스 로직(핵심 기능) |
[AOP 용어들]
▷핵심 로직 관련
Target 객체 : 주요 핵심 로직 객체 자체. 순수한 Core JointPoint : Target 객체가 가진 여러 메소드들. |
▷주변 로직(관심사) 관련
Aspect (추상) : 관심사의 추상화 객체 Advice (구현) : Aspect를 구현한 실질적인 관심사 객체 |
▷엮는 애들
Pointcut : 핵심로직과 관심사 엮는 설정 : Target의 어떤 JointPoint 지점에서 Advice를 엮을지 설정하는 부분 1) XML 이용한 설정 2) @어노테이션 이용한 설정 |
▷결합 완성품
Proxy : 결합의 완성품 : Pointcut에 의해 핵심 Target과 Advice가 결합된 상태 : 전체적인 결합체를 감싸고 있는 존재 - Proxy는 내부적으로 Target을 호출하지만. 실행 시 중간에 필요한 관심사들을 거쳐서 Target 호출하도록 설계되어 있다. |
[Pointcut의 주요 사용 설정]
execution (@execution) | 메서드 기준으로 Pointcut 설정 |
within (@within) | 특정 클래스 타입 기준으로 Pointcut 설정 |
this | 주어진 인터페이스 구현 객체 기준으로 Pointcut 설정 |
args (@args) | 특정 파라미터 가진 대상들만 기준으로 Pointcut 설정 |
@annotaion | 특정 어노테이션 적용 대상들만 기준으로 Pointcut 설정 |
[Advice 동작 위치에 따른 분류]
Before Advice | pointcut 메소드 호출 전 실행 - > Advice 실행 |
After Returning Advice | pintcut 메소드 익셉션 없이 실행 이후 - > Advice 실행 |
After Throwing Advice | pointcut 메소드 실행 도중 익셉션 발생 가능한 경우 - > Advice 실행 |
After Advice | (익셉션 발생여부와 관련X) pointcut 메소드 실행 후 - > Advice 실행 |
Around Advice | pointcut 메소드 실행 전/후 또는 익셉션 발생 시점 - > Advice 실행 |
▶[AOP 실습]
[공통 - AOP 설정 준비]
AspectJ Weaver 라이브러리가 가장 중요
pom.xml에 <aspectjweaver> 의존 추가 필요
스프링은 AOP 처리된 객체 생성 시 AspectJ Weaver라이브러리 도움 받아서 동작함
① XML 이용한 AOP 구현 방법
[핵심 객체 준비] : Target 객체
public class TestBean { //Target 객체
public int method1() { //jointPoint
System.out.println("method1 호출");
return 100;
}
}
[관심사 객체 준비] : Advice (=Aspect) 객체
public class AdvisorClass { // (1) XML로 AOP 구현 시 '관심사 객체'
public void beforeMethod() {
System.out.println("beforeMethod 호출");
}
public void afterMethod() {
System.out.println("afterMethod 호출");
}
public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("aroundMethod 호출1");
// 원래의 메서드를 호출한다.
Object obj = pjp.proceed();
System.out.println("aroundMethod 호출 2");
return obj;
}
public void afterReturningMethod() {
System.out.println("afterReturningMethod 호출");
}
public void afterThrowingMethod(Throwable e1) {
System.out.println("afterThrowingMethod 호출");
System.out.println(e1);
}
}
[XML 이용한 AOP 설정]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id='xml1' class='kr.co.softcampus.beans.TestBean'/> //Target객체 빈 등록
<bean id='advisor1' class='kr.co.softcampus.advisor.AdvisorClass'/> //Advice 빈 등록
<aop:config> // AOP 설정
<aop:aspect ref='advisor1'>
<aop:pointcut id="point1" expression="execution(* method1())"/> //pointcut 설정
//동작 위치별 Advice 설정
<aop:before method="beforeMethod" pointcut-ref="point1"/>
<aop:after method="afterMethod" pointcut-ref="point1"/>
<aop:around method="aroundMethod" pointcut-ref="point1"/> <aop:after-returning method="afterReturningMethod" pointcut-ref="point1"/>
<aop:after-throwing method="afterThrowingMethod" pointcut-ref="point1" throwing="e1"/>
</aop:aspect>
</aop:config>
</beans>
[실행 Main]
public class MainClass { //실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext("kr/co/softcampus/config/beans.xml");
//xml 설정 컨테이터 생성
TestBean bean1 = ctx.getBean("xml1", TestBean.class); // Target 빈 객체를 getBean()
int a1 = bean1.method1(); //Target객체의 pointcut에 설정된 메소드 실행
//이때 beans.xml 설정 파일에 지정해놓은 Advice들이 동작 위치별로 핵심 로직과 함께 실행된다.
System.out.printf("a1 : %d\n", a1);
ctx.close();
}
}
[실행 결과 화면]
② Java 설정 이용한 AOP 구현 방법
[핵심 객체 준비] : Target 객체
@Component //이 객체를 자동 빈 등록
public class TestBean1 {
public void method1() { // 얘를 핵심 Target객체의 jointPoint라고 생각해보자
System.out.println("TestBean1의 method1() 호출");
}
}
[관심사 객체 준비] : Advice (=Aspect) 객체
@Component //우선 자동으로 빈 등록 설정
@Aspect //얘를 관심사로 인식할 수 있게 지정
public class AdvisorClass { // (2) Java 설정으로 AOP 구현 시 '관심사' 클래스
@Before("execution(* method1())")
public void beforeMethod() {
System.out.println("beforeMethod()호출 ");
}
@After("execution(* method1())")
public void afterMethod() {
System.out.println("afterMethod() 호출");
}
@Around("execution(* method1())")
public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("aroundMethod 호출 1");
Object result = pjp.proceed() ;
System.out.println("aroundMethod 호출 2");
return result;
}
@AfterReturning("execution(* method1())")
public void afterReturningMethod() {
System.out.println("afterReturningMethod 호출 ");
}
@AfterThrowing("execution(* method1())")
public void afterThrowingMethod() {
System.out.println("afterThrowingMethod 호출");
}
}
[Java 이용한 AOP 설정]
@Configuration
@ComponentScan(basePackages = {"kr.co.softcampus.beans", "kr.co.softcampus.advisor"})
@EnableAspectJAutoProxy //@AspectJ 이용해서 관심사로 등록해놓은 클래스를 자동으로 프록시 객체로 인식할 수 있게 설정
public class BeanConfigClass {// 빈 설정 클래스
}
[실행 Main]
public class MainClass { // 실행 Main
public static void main(String[] args) {
//Java 설정 파일로 컨테이너 객체 생성
AnnotationConfigApplicationContext ctx2
= new AnnotationConfigApplicationContext(BeanConfigClass.class);
TestBean1 java1 = ctx2.getBean(TestBean1.class); //Target 객체 getBean
java1.method1(); //pointcut된 메소드 실행
//실행 시, 동작 위치별로 관심사 Advice 지정해놓은 대로 실행됨
ctx2.close();
}
}
[실행 결과 화면]
728x90
'Web(웹)_관련 공부 모음 > [학교]_STS_Spring_실습' 카테고리의 다른 글
[학교]_9주차_스프링 JDBC 실습 (0) | 2022.05.03 |
---|---|
[학교]_MySQL 설치 (0) | 2022.04.26 |
[학교]_7주차_스프링 AOP 실습 (0) | 2022.04.20 |
[학교]_6주차_스프링 @ComponentScan 실습 (0) | 2022.04.12 |
[학교]_5주차_스프링 @Qualifier 실습 (0) | 2022.04.05 |