필요한 용어 정리
1)의존성 주입(DI, Dependency Injection)
-클래스 객체를 개발자가 코드에서 생성하지 않고 프레임워크가 생성하여 사용하는 방법
2)제어 역행(IoC, Inversion of Control)
-서블릿이나 빈 등을 개발자가 코드에서 생성하지 않고 프레임워크가 직접 수행하는 방법
3)관점 지향(AOP, Aspect-Oriented Programming)
-핵심 기능 외 부수 기능들을 분리 구현함으로써 모듈성을 증가시키는 방법
IoC
IoC (Inversion of Control) : 제어의 역전
-인스턴스 생성 ~ 소멸까지의 인스턴스 생명 주기 관리를 개발자가 아닌
컨테이너가 대신 해줌.(역전)
-컨테이너 역할을 해주는 프레임워크에게 제어하는 권한을 넘겨서 개발자의 코드가
신경 써야 할 것을 줄이는 전략.
-프레임워크 동작 원리가 반대로 동작하므로 IoC라고 부른다.
-Spring 컨테이너는 IoC를 지원함.
DI
DI (Dependency Injection) : 의존성 주입
-객체 자체가 아니라 Framework에 의해 객체의 의존성이 주입되는 설계 패턴
-개발자들은 빈 설정 파일에서 의존 관계가 필요하다는 정보만 주입하면 됨.
-생성자, 메소드의 setter, 멤버 변수에 @Inject, @Autowired를 통해 주입.
-객체 레퍼런스를 컨테이너로부터 주입받아서 실행 시 동적으로 의존 관계가 생성됨.
-컨테이너가 흐름의 주체가 되어 애플리케이션 코드에 의존 관계를 주입해 주는 것.-장점 : 코드가 단순해짐, 컴포넌트 간 결합도 제거됨.
AOP
AOP (Aspect-Oriented Programming) : 관점 지향 프로그래밍
-개발을 하다보면 반복되는 작업들이 있다. -> 이것들의 공통 작업을 모아 필요한 적절 시기에 적용하는 개념
<관점 지향 프로그래밍의 등장?>
1)주기능인 회원 등급 구현 시 로깅 기능, 보안 기능, 트랜잭션 기능 등의 보조 기능을 일일이 구현해야함.
2)규모가 있는 웹 애플리케이션일 경우 이런 작업을 수작업으로 하기에는 소스 코드가 복잡해지고 유지 관리가 어려울 수 있음.
=>AOP를 이용해서 주기능과 보조 기능을 분리해서 메서드에 적용!!
1. AOP 개요
1)애플리케이션에서의 관심사의 분리(기능의 분리), 핵심 기능에서 부가 기능을 분리함.
2)분리한 부가 기능을 애스팩트(Aspect)라는 모듈 형태로 개발하는 방법.
2. 핵심 기능과 부가 기능
1)업무(Biz)로직을 포함하는 기능을 핵심 기능(Core Concerns)
2)핵심기능을 도와주는 부가적인 기능(로깅, 보안 등)을 부가 기능(Cross-cutting Concerns)
3)객체 지향의 기본 원칙을 적용해도 핵심 기능에 부가 기능을 분리해서 모듈화하기는 어려움.
3. AOP 용어
1)애스팩트(Aspect)
-부가 기능을 정의한 코드인 어드바이스(Advice) + 어드바이스를 어디에 적용할지 결정하는 포인트컷(PointCut) 합친 것.
Advice + PointCut = Aspect
-AOP의 기본 모듈
-싱글톤 형태의 객체로 존재함
-어드바이스(Advice) : 핵심 기능에 제공할 부가 기능을 담고 있는 모듈
-조인 포인트(Join Point) : 어드바이스가 적용될 수 있는 위치.
-포인트컷(PointCut) : 어드바이스를 적용할 타겟의 메서드를 선별하는 정규 표현식, execution으로 시작함.
-핵심 기능 코드 사이에 부가된 부가 기능을 독립적인 애스팩트로 구분할 수 있음.
2)타켓(Target)
-핵심 기능을 담고 있는 모듈
-타겟은 부가 기능을 부여할 대상이 된다.
3)위빙(Weaving)
-포인트컷에 의해서 결정된 타겟의 조인 포인트에 부가 기능(어드바이스)을 삽입하는 과정
-위빙은 AOP가 핵심 기능(타겟)의 코드에 영향을 주지 않으면서 필요한 부가 기능(어드바이스)을
추가할 수 있도록 해주는 처리 과정이다.
4. Spring AOP 특징
1)Spring은 타겟(Target)객체에 대한 프록시를 만들어 제공함.
2)타겟을 감싸는 프록시는 실행시간(Runtime)에 생성됨.
3)프록시 : 어드바이스를 타갯 객체에 적용하면서 생성되는 객체
4)프록시가 호출을 가로챔(Intercept)
-프록시는 타겟 객체에 대한 호출을 가로챈 다음
어드바이스의 부가 기능 로직을 수행하고 난 후에
타겟의 핵심 기능 로직을 호출함(선처리 어드바이스)
-타겟의 핵심 기능 로직 메서드를 호출한 후에
부가 기능(어드바이스)을 수행하는 경우(후처리 어드바이스)
AOP 예제
사용된 라이브러리
AOPTest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="calcTarget" class="kr.co.ezenac.aop.Calculator" /> <!-- 타깃 클래스 빈 -->
<bean id="logAdvice" class="kr.co.ezenac.aop.LoggingAdvice" /> <!-- 로그 기능을 하는 어드바이스 빈 -->
<!-- 스프링 프레임워크에서 제공하는 ProxyFactoryBean을 이용해 타겟과 어드바이스를 엮어줌 -->
<bean id="proxyCal" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="calcTarget"/> <!-- 타겟 빈을 calcTarget 빈으로 지정 -->
<property name="interceptorNames"> <!-- logAdvice를 어드바이스 빈으로 설정 -->
<list>
<value>logAdvice</value>
</list>
</property> <!-- =>타깃 클래스의 메서드 호출 시 logAdvice를 실행함 -->
</bean>
</beans>
|
cs |
CalcTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CalcTest {
public static void main(String[] args) {
//AOPTest.xml을 읽어 들여 빈을 생성함.
//애플리케이션 컨텍스트 : BeanFactory를 확장한 IoC 컨테이너
// Bean을 등록, 관리하는 기능, 스프링이 제공하는 각종 부가 서비스를 제공.
ApplicationContext context = new ClassPathXmlApplicationContext("AOPTest.xml");
Calculator cal = (Calculator)context.getBean("proxyCal");
cal.add(100, 20); //메서드 호출 전후에 어드바이스 빈이 적용됨.
System.out.println();
cal.substract(100, 20);
System.out.println();
cal.multiply(100, 20);
System.out.println();
cal.divide(100, 20);
}
}
|
cs |
Calculator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/*
* AOP 기능 구현 과정
* 1)타겟(Target) 클래스
* 2)어드바이스(Advice) 클래스
*/
public class Calculator {
public void add(int x, int y) {
int result = x + y;
System.out.println("결과 :" + result);
}
public void substract(int x, int y) {
int result = x - y;
System.out.println("결과 :" + result);
}
public void multiply(int x, int y) {
int result = x * y;
System.out.println("결과 :" + result);
}
public void divide(int x, int y) {
int result = x / y;
System.out.println("결과 :" + result);
}
}
|
cs |
LoggingAdvice.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.aopalliance.intercept.MethodInterceptor;
public class LoggingAdvice implements org.aopalliance.intercept.MethodInterceptor{
/*
* 해당 메서드의 실행 전/후와 예외 발생 시 실행
* MethodInvocation : 호출된 메서드, 인자 (타겟 객체의 정보를 담고 있는 객체)
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("[(타겟) 메서드 호출 전] : LoggingAdvice " );
System.out.println(invocation.getMethod() + "메서드 호출 전");
invocation.proceed();
System.out.println("[(타겟) 메서드 호출 후] : LoggingAdvice " );
System.out.println(invocation.getMethod() + "메서드 호출 전");
return null;
}
}
|
cs |
실행 결과 콘솔창
'📒 education archive > 🌿Spring' 카테고리의 다른 글
[국비학원 기록/Spring] 트랜잭션(Transaction), 두 개의 계좌에 대한 동시 계좌이체 구현 예제 (0) | 2022.01.04 |
---|---|
[국비학원 기록/Spring] 마이바티스 MyBatis Framework 사용, 회원 정보 조회, 수정, 삭제 예제 (0) | 2022.01.04 |
[국비학원 기록/Spring] 스프링 MVC 패턴, model1, model2 (0) | 2022.01.02 |
[국비학원 기록/Spring] 의존성 주입, setter, 생성자 예제 (0) | 2022.01.02 |
[국비학원 기록/Spring] 프레임워크란? (0) | 2022.01.02 |