Backend boot camp/Session2
Spring Framework Cores(DI/AOP)
by orioncsy
2022. 10. 18.
DI(Dependency Injection)
Spring Container
Spring Container
- spring framework의 핵심 컴포넌트
- 내부에 존재하는 애플리케이션 빈의 생명 주기 관리
- 개발자가 정의한 bean을 객체로 만들어 생성, 제거, 제공 등 관리
- 원하는 만큼의 객체를 소유
- public interface ApplicationContext extends ...{}
- 인터페이스로 구현하고 다형성 적용하여 ApplicationContext로 선언
- 의존성 주입(DI)으로 애플리케이션 컴포넌트 관리
- bean을 서로 연결하는 역할
- 개발자는 의존, 결합 문제에서 자유로움
- 메서드 호출 시기, 위치, 매개변수 준비하지 않음
Spring Container 사용 목적
- 객체를 사용하기 위한 new 키워드를 사용하는 단점 보안
- 참조가 심하여 의존성이 높아 결합성이 높아져 캡슐화에 방해
- 의존성을 낮추기 위해 spring container 사용
- 참조) 객체지향 프로그래밍 목표 - 낮은 결합도(의존성)와 높은 응집도(캡슐화)
- 정책이 변경되거나 추가될 경우 의존성이 높아지는데 이것을 제거하고 인터페이스에 의존시킴
Spring container 생성 방식
- Spring container는 Configuration Metadata 사용
- 매개변수로 들어온 설정 클래스 정보에 따라 스프링 빈을 등록
- new AnnotationConfigApplicationContext(구성정보 클래스)로 bean 등록
- Java 기반 Annotation 방식
- ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
- XML 방식
- <beans />에 필요한 값들을 설정
- <bean id=” …”> 빈의 ‘고유한’ 정의 식별 문자열
- <bean class=” …”> bean ‘유형’ 정의
- 스프링 컨테이너를 생성하는 방법 - ApplicationContext 인터페이스 구현체
- AppConfig.class와 같은 구성 정보를 지정해서 스프링 컨테이너 생성
- AppConfig에 있는 정보로 필요한 객체 생성
- 구성 정보 같은 메타데이터와 결합해서 ApplicationConetext 생성, 초기화 후 실행 가능한 애플리케이션
- 스프링 빈 조회할 때 상속관계가 존재하면 부모 타입 조회하면 자식 타입도 함께 조회
- object 타입 조회하면 모든 bean 조회
- ApplicationContext 인터페이스 확인법
- ctrl + N or cmd + O에서 ApplicationContext 검색
Spring container type
- Spring Container : 설정 클래스 정보를 참고해서 빈 생성, 관계 설정 제어 역할 총괄
- BeanFactory
- Spring Container의 최상위 인터페이스
- 빈 등록, 생성, 조회, 반환
- getBean()으로 빈 인스턴스화
- @Bean이 붙은 메서드명을 빈 이름으로 사용해서 빈 등록
- ApplicationContext
- BeanFactory 기능 상속받아 처리
- BeanFactory가 빈 관리, 검색 기능 / ApplicationContext는 그 외 부가기능
- ApplicationContext 기능
- MessageSource 메시지 다국화
- EnvironmentCapable 개발, 운영을 나누어 처리하고 애플리케이션 필요 정보 관리
- ApplicationEventPublisher 이벤트 관련 기능
- ResourceLoader 리소스 조회
New 키워드에 비교한 주입 코드(DI) 특징
- 생성자에 객체를 주입하여 IoC/DI 구현
- 의존을 하는 객체에서는 생성자에 어떤 객체가 오는지 알 필요 없음
- 의존하는 객체는 실행에만 집중
- 어떤 객체가 오는지는 AppConfig 같은 외부 객체에서 정함
Bean
개념
- Spring Container에서 관리되는 재사용 소프트웨어 컴포넌트
- 인스턴스화 된 객체를 의미
- spring container에 등록된 객체를 spring bean
- @Bean이 적힌 메서드를 모두 호출해서 반환된 객체를 spring container에 등록
- Bean에는 등록정보, getter, setter 포함
- 설정 메타데이터로 컨테이너에서 생성
- 설정 메타데이터는 XML, java annotation, java로 구현 가능
- 컨테이너의 명령, 인스턴스화, 설정, 조립 객체 정의
접근 방법
- ApplicationContext로 객체를 생성한다
- 생성된 객체에서 getBean() 메서드를 통해 bean 인스턴스 가져옴
- bean의 인스턴스에서 정보를 가져온다
BeanDefinition
- BeanDefinition(빈 설정 메타정보)으로 bean을 정의하고 활용
- 속성에 따라 bean의 생성 관리 결정
- @Bean이나 <bean>에 1개씩 메타 정보 생성
- 설정 메타정보를 BeanDefinition 인터페이스를 통해 관리하여 XML, Java로 컨테이너 설정 가능
- BeanDefinition이 포함하는 메타정보
- 패키지 수식 클래스 이름 : 빈의 구현 클래스
- bean동작 구성 요소 : 컨테이너에서 bean 동작 설명(범위, 수명)
- 다른 bean에 대한 참조
- 새로 만든 개체에 대한 구성 설정
- 각 빈 정의를 구성하는 속성 집합
- BeanClassName - 빈 클래스 명
- factoryBeanName - 팩토리 역할 빈의 이름
- factoryMethodName - 팩토리 메서드 지정
- Scope - 싱글톤
- lazyInit - 실제 빈을 생성하지 않고 최대한 생성 지연처리 여부
- InitMethodName - 빈 생성하고 호출한 뒤에 초기화 메서드 이름
- DestroyMethodName - 생명 주기 끝나 제거하기 전에 호출되는 메서드 이름
- Constructor arguments, Properties - 의존관계 주입에 사용
Bean Scope
개념
- bean이 존재할 수 있는 범위
- 특정 bean 정의에서 생성된 개체에 연결할 의존성과 범위 정의 가능
- 6개의 범위를 지원, 그중 4개는 ApplicationContext를 사용하는 경우 이용 가능
- bean 여러 범위 중 하나에 배치
- 개체의 범위를 선택 가능
- 사용자 정의 범위도 가능
- Type
- singleton - defualt로 단위 객체 인스턴스에 대한 단일 bean definition 범위 지정
- prototype - 프로토타입 빈의 생성과 의존 관계 주입만 관여
- request - 웹 요청 들어오고 나가는 스코프
- session - 세션이 생성, 종료 유지 스코프
- application - 웹 서블릿 컨텍스와 같은 범위
- websocket - 단일 bean definition 범위를 WebSocket의 라이프사이클까지 확장, ApplicationContext에서만 유효
Singleton Scope
- 클래스 인스턴스가 1개만 생성되도록 보장하는 디자인 패턴
- 컨테이너 시작과 종료까지 유지
- 싱글톤 빈의 하나의 공유 인스턴스만 관리
- private으로 외부에서 new를 생성하지 못하도록 방지
- bean definition과 일치하는 ID를 갖는 빈에 대한 요청은 특정 빈 인스턴스를 반환
- 컨테이너 종료 시 소멸 메서드 자동 실행
- 싱글톤 패턴 적용
- static 객체 인스턴스를 미리 1개 생성
- 객체 인스턴스가 필요한 경우 getInstance()를 통해 조회만 가능
- 외부에서 new로 생성자 호출 못하도록 private으로 막는다
- 싱글톤 패턴의 문제점
- 구현 코드 다양
- 클라이언트가 구체 클래스에 의존
- 지정해서 가져와서 테스트가 어려움
- private 생성자로 자식 클래스 생성 어려움
- 속성 공유
- 멀티 스레드 환경에서 객체 속성 바뀔 수 있음
- 도중에 바뀌게 되면 잘못된 값을 반환 가능
- 읽기만 가능해야 함
- Application 초기 구동에 인스턴스 생성
- 싱글톤 패턴의 문제점을 싱글톤 컨테이너가 해결
- 스프링 컨테이너는 싱글톤 컨테이너 역할
- 싱글톤 객체로 생성, 관리하는 기능을 싱글톤 레지스트리
- 스프링 컨테이너가 위의 문제점을 해결하고 싱글톤 유지
- @Configuration으로 구성정보 담당 설정
- @Bean을 통해 스프링 컨테이너에 등록
- static AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.clss)
- .getBean(”name”, [클래스명.class])로 호출
- 싱글톤 객체는 무상태로 설계
- 특정 클라이언트가 값을 변경하면 안 됨
- 일기만 가능
- 공유 값 설정하면 오류 발생
Java 기반 컨테이너 설정
@Bean & @Configuration
- 메서드에 Spring 컨테이너에 관리할 새 객체를 인스턴스화, 구성, 초기화한다는 것을 나타내는 데 사용
@Configuration
public class AppConfig{
@Bean
public UserService userService(){
return new UserService();
}
}
<beans>
<bean id="userService" class="com.service.UserService"/>
</beans>
AnnotationConfigApplicationContext
- @Configuration Class
- 파라미터로 전달받으면 @Configuration class 자체가 bean 정의로 등록되고 클래스 내 모든 @Bean 메서드도 bean정의로 등록
- @Componenet Class / JSR-330 메타데이터
- 빈 정의로 등록되고 @Autowired 혹은 @Inject 같은 DI 메타데이터가 사용될 수 있음
- @Autowired를 사용하면 해당 Type에 따라 자동으로 bean 주입
- @Configuration class 예제
public static void main(String[] args){
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = ac.getBean(UserService.class);
}
- @Component Class / JSR-330 메타데이터 예제
public static void main(String[] args){
ApplicatgionContext ac = new AnnotaitonConfigApplicationContext(UserService.class, Dependency1.class)
UserService userService = ac.getBean(UserService.class);
}
@Bean 사용
- 메서드 레벨 애너테이션으로 <bean/>에서 제공하는 속성 제공
- init-method
- destroy-method
- autowiring
- Bean 선언
- @Configuration과 @Bean 선언하여 구현
- XML에서 </beans> 안에 <bean id=”…” class=”..”>로 구현
- 빈 정의가 있는 인터페이스를 구현하고 @Configuration과 implements을 선언하여 구현
- @Bean 객체의 이름은 메서드 이름으로 저장됨
@Configuration 사용
- bean definition의 소스임을 나타내는 애너테이션
- @Bean-annoted 메서드를 통해 bean 생성
- @Bean 메서드 호출 bean 사이 의존성 정의
- Bean 사이의 의존성 주입/java 기반으로 설정된 환경에서 내부적으로 작동하는 방식 정보
Java에서 Spring container 구성
- @Import(Config.class)
- XML 파일 내 요소 사용처럼 모듈화 하는 데 사용
- 다른 구성 클래스에서 @Bean definitions를 가져올 수 있음
Component Scan
Component scan
- 설정 정보 없이 자동으로 빈 등록
- @ComponentScan은 @Component가 붙은 모든 클래스를 스프링 빈으로 등록
- 의존 관계에서 자동으로 주입하는 @AutoWired 기능 제공
사용 방법
- @Configuration에 @Component가 있기 때문에 @ComponentScan으로 자동으로 빈 등록 가능
- 기존 @Configuration 설정이 된 파일 있을 때
- @ComponentScan(excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Configuration.class)) 추가
- XML 방식 component scan
<beans>
<context:component-scan base-package="com.acme"/>
</beans>
@Component & @Autowired
- 클래스 앞에 @Component 선언하여 @ComponentScan에서 해당 객체를 가져올 수 있음
- @Autowired를 사용하여 생성자 의존성 주입에 필요한 설정 정보 대신 의존관계 자동 주입
basePackages
- 탐색할 패키지의 시작 위치 지장, 하위 패키지까지 모두 탐색
- @ComponentScan()의 매개변수로 basePackages=””지정 가능
- 지정을 안 하면 @ComponentScan이 붙은 설정 정보 클래스 패키지가 시작 위치
- @SpringBootApplication을 프로젝트 시작 위치에 두는 것도 가능
- @SpringBootApplication안에 @ComponentScan이 존재
Component Scan 대상
- @Component - 컴포넌트 스캔 대상
- @Controller & @RestController - 스프링 MVC, REST 전용 컨트롤러
- @Service - 스프링 비즈니스 로직에 사용
- 특별한 처리 없이 핵심 비즈니스 로직이라는 것을 알리기 위해 사용
- @Repository - 스프링 데이터 접근 계층에서 사용
- 데이터 접근 계층으로 인식하고 데이터 계층 예외를 스프링 예외로 변환
- @Configuration - 스프링 설정 정보에서 사용
- 스프링 설정 정보로 인식, 스프링 빈이 싱글 톤 유지하도록 추가 처리
필터
- includeFilters - 컴포넌트 스캔 대상 추가
- excludeFilters - 컴포넌트 스캔 제외
- FilterType 옵션
- ANNOTATION - 기본값
- ASSIGNABLE_TYPE - 지정 타입, 자식 타입 인식
- ASPECTJ - AspectJ 패턴 사용
- REGEX - 정규 표현식
- CUSTOM - TypeFilter 인터페이스 구현 처리
의존관계 주입 방식
1. 생성자 주입
- 생성자를 통해서 의존관계를 주입하는 방식
- 생성자에 @Autowired를 하면 @Component로 등록된 빈에서 생성자에 필요한 빈 주입
- 생성자 호출 시점 1번만 호출
- 불변과 필수 의존 관계에서 사용
- 생성자가 1개만 존재하는 경우 @Autowired 생략 가능
- NullPointerException 방지
- 주입받을 필드 final로 선언 가능
2. 수정자 주입(setter 주입)
- setter라 불리는 필드의 값을 변경하는 수정자를 통해 의존 관계 주입
- 선택과 변경 의존 관계에서 사용
- 자바 빈 프로퍼티 규약의 수정자 메서드 방식 사용
- Autowired롤 입력해야 한다
3. 필드 주입
- 필드에 @Autowired를 붙여서 바로 주입하는 경우
- 외부에서 변경 불가하고 테스트 어려움
- 실제 코드와 상관없는 특정 테스트할 때 사용
- 정상 작동을 위해 setter가 필요하다
4. 일반 메서드 주입
- 일반 메서드에 주입
- 한 번에 여러 필드를 주입받는 것 가능
- 일반적으로 사용 안 함
옵션 처리
- 주입할 스프링 빈이 없을 때 동작하게 하기 위한 처리
- 스프링 빈을 옵셔널로 해두고 사용
- @Autowired(required=false) - 자동 주입 대상 없으면 수정자 메서드 자체가 호출 안됨
- org.springframework.lang.@Nullable - 자동 주입 대상 없으면 null 입력
- Optional <> - 자동 주입 대상이 없으면 Optional.empty 입력
생성자 주입을 사용하는 이유
- 불변
- 의존 관계 주입은 종료 때까지 변경되지 않고 변경되면 안 된다
- 수정자 주입은 이름 메서드를 public으로 열어서 변경 가능해서 부적합
- 생성자 주입으로 객체 생성할 때 1번만 호출하고 그 이후에 변경하지 않아 불변 구현 가능
- 누락
- 호출했을 때 NPE 발생 가능한데 의존관계 주입 누락되어서 발생
- 생성자 주입을 사용하면 컴파일 오류로 발생
- final 키워드 사용 가능
- 생성자 이외의 주입 방식은 생성자 호출 이후에 부르기 때문에 final 키워드 사용 불가
- 생성자에서 값이 설정되지 않으면 컴파일 오류
- 순환 참조
- 순환 참조 방지
- 여러 컴포넌트 간에 의존성이 생기고 A→B , B→A로 참조 가능
- 다른 주입 방식은 빈 생성 이후 호출되기 때문에 오류 발생이 없다
- 생성자 주입은 BeanCurrentlyInCreationException 발생
생성자 주입 방식 장점
- 의존 관계 설정이 안 되면 객체 생성 불가
- final로 선언 가능
- 순환 참조 감지 가능
- 테스트 코드 작성 용이
- 수정자 주입은 옵션이 필요할 때만 선택
AOP(Aspect Oriented Programming)
Aspect
- 부가 기능과 그 기능들을 어디에 적용할지 선택하는 기능을 합한 하나의 모듈
- 애플리케이션을 바라보는 관점을 기능을 바라보는 관점, 즉 횡단 관심사(cross-cutting concerns)
AOP
등장 배경
- OOP만 구현해서는 비즈니스 코드에서 관심사 분리(Seperation of Concerns, SoC)를 하여 횡단 관심사 코드를 분리하기 어려워 AOP 등장
개념
- 객체 중심으로 구현하는 OOP의 단점을 보완하기 위해 관점을 분리하고 여러 유형과 객체 간 발생 문제를 모듈화가 가능하게 한다
- 객체마다 존재하는 공통 부가 기능들을 따로 분리하여 적용함으로써 불필요한 코드 반복을 최소화
구성
- 핵심 기능(Core Concerns) : 객체가 제공하는 고유 업무 로직 담당
- 부가 기능(Cross-cutting Concerns) : 핵심 기능을 도와주는 역할
- 단독으로 사용하지 않고 핵심 기능과 함께 사용
- 여러 클래스에 걸쳐 적용되어 cross-cutting concerns(횡단 관심사)로 존재
- 보안, 트랜잭션, 로깅
- 객체 안에 핵심 기능, 부가 기능이 합쳐져 하나의 로직으로 실행
관련 용어
- Aspect
- 여러 객체에 공통으로 적용되는 기능(cross-cutting concerns)
- Advice + PointCut
- Advice - 부가 기능 정의
- PointCut - 부가 기능을 어디에 적용할지 결정
- Join point
- 애플리케이션 실행 흐름에서 특정 포인트 지칭
- AOP를 적용할 수 있는 모든 지점을 지칭
- 새로운 동작을 추가하기 위해 join point에 aspect code 추가 가능
- Spring AOP는 프록시 방식 사용 - join point는 메서드 실행 지점으로 제한
- 어드바이스 적용이 필요한 곳은 메서드 존재
- Advice
- join point에서 수행되는 부가 기능 코드
- Aspect를 언제 핵심 코드에 넣을지 정의
- 전체 aspect에 API 호출 제공
- 메서드 호출 전 로그로 남기기 위해 시작 전 조인 포인트를 선택
- PointCut
- join point 중에 advice가 적용될 위치 선별
- AspectJ 표현식으로 지정
- 프록시를 사용하는 Spring AOP에서는 메서드 실행 지점만 선별 가능
- Weaving
- PointCut으로 결정된 join point에 advice 적용하는 것
- 핵심 코드에 영향을 주지 않고 부가 기능 추가
- AOP 적용을 위해 객체 연결
- 컴파일 타임(AspectJ compiler), 로드 타임, 런타임
- AOP proxy
- AOP 구현을 위해 만든 proxy 객체
- Spring AOP에서는 JDK 동적 프록시, CGLIB 프록시
- Target
- 핵심 기능을 담고 있는 모듈
- 부가 기능 부여 대상
- Advice 받는 객체이고 pointCut으로 결정
- Advisor
- 하나의 advice와 하나의 pointCut으로 구성
Advice
순서
- 기본적으로 순서를 보장하지 않음
- 순서를 지정하기 위해서 @Aspect 적용 단위로 org.springframework.core.annotation.@Order 적용
- 클래스 단위로 적용
- 여러 advice가 존재하면 순서 보장 안됨
- aspect를 별도의 클래스로 분리
종류
- Before
- join point 이전에 실행
- 타깃이 실행되기 전 공통 기능을 실행
- 리턴 타입이 void
- 메서드에서 예외 발생할 경우 메서드 호출하지 않음
- After returning
- join point 정상 완료 후 실행
- 메서드 실행 후 공통 기능 실행
- returning 속성에 사용된 이름은 메서드 매개변수 이름과 일치
- returning 절에 지정된 타입을 반환하는 메서드만 대상
- After throwing
- 메서드가 예외를 던지는 경우 공통 기능 실행
- throwing 속성에 사용된 이름이 메서드 매개변수 이름과 일치
- throwing 절에 지정된 타입과 맞는 예외를 대상으로 실행
- After (finally)
- join point 작동과 상관없이 공통 기능 실행
- 리소스 해제할 때 사용
- Around
- 메서드 전후, 예외 발생 시점에 수행
- joinPoint.proceed() - 조인 포인트 실행 여부
- joinPoint.proceed(args[]) 전달 값 변환
- 반환 값 변환
- 예외 변환
- try - catch - finally 구문 처리 가능
- 첫 번째 파라미터는 ProceedingJoinPoint 사용
- proceed()를 통해 대상 여러 번 실행 가능
Pointcut 표현식
- 관심 조인 포인트를 결정하여 어드바이스 실행 시기 제어
- AspectJ가 제공하는 pointcut expression
포인트 컷 지시자 종류
- execution - 메서드 실행 조인 포인트 매칭
- within - 특정 타입 내 조인 포인트 매칭
- args - 인자가 주어진 타입의 인스턴스 조인 포인트
- this - 스프링 빈 객체를 대상으로 하는 조인 포인트
- target - target 객체를 대상으로 하는 조인 포인트
- @target - 실행 객체의 클래스에 주어진 타입의 애너테이션이 있는 조인 포인트
- @within - 주어진 애너테이션이 있는 타입 내 조인 포인트
- @args - 인수로 주어진 타입의 애너테이션을 갖는 조인 포인트
- bean - 스프링 전용, 빈의 이름으로 포인트 컷 지정
Pointcut 표현식 결합
- anyPublicOperation - 메서드 실행 조인 포인트가 공용 메서드 실행을 나타내는 경우 일치
- inTrading - 메서드 실행이 거래 모듈에 있는 경우 일치
- tradingOperation - 메서드 실행이 거래 모듈의 공개 메서드를 나타내는 경우 일치
일반적인 pointcut 표현식들
- execution(public * *(..))
- execution(* set*(..))
- execution(* com.xyz.service.AccountService.*(..))
- AccountService 인터페이스에 의해 정의된 모든 메서드의 실행
- execution(* com.xyz.service.*.*(..))
- execution(* com.xyz.service..*.*(..))
- service 패키지 또는 하위 패키지 중 하나에 정의된 메서드 실행
- within(com.xyz.service.*)
- within(com.xyz.service..*)
- service 패키지 또는 하위 패키지 중 하나 내 모든 조인 포인트
- this(com.xyz.service.AccountService)
- AccountService 프록시가 인터페이스 구현하는 모든 조인 포인트
- target(com.xyz.service.AccountService)
- AccountService 대상 객체가 인터페이스를 구현하는 모든 조인 포인트
- args(java.io.Serializable)
- 단일 매개변수 사용하고 런테임에 전달된 인수가 Serializable과 같은 모든 조인 포인트
- @target(org.springframework.transaction.annotation.Transactional)
- 대상 객체에 @Transactional 이 있는 모든 조인 포인트
- @annotation(org.springframework.transaction.annotation.Transactional)
- 실행 메서드에 @Transactional이 있는 조인 포인트
- @args(com.xyz.security.Classified)
- 단일 매개변수에 전달된 인수의 런타임 유형이 @Classified를 갖는 조인 포인트
- bean(tradeService)
- tradeService라는 이름을 가진 스프링 빈의 모든 조인 포인트
- bean(*Service)
- 와일드 표현식, *Service라는 이름을 가진 스프링 빈의 모든 조인 포인트
Join Point
적용 위치
- AOP 적용 위치 - 생성자, 필드 값 접근, static 메서드 접근, 메서드 실행
- AOP 수행하는 메서드는 joinpoint 인스턴스를 인자로 받는다
- joinpoint 인스턴스에서 joinpoint 지점 정보 획득
특징
- AspectJ를 사용해서 컴파일 시점과 클래스 로딩 시점에 적용하는 AOP는 바이트 코드를 조작하여 모든 지점에 적용 가능
- 프록시 방식을 사용하는 스프링 AOP는 메서드 실행 지점에만 적용 가능
- 스프링 빈에만 AOP 적용 가능
- 프록시는 메서드 오버라이딩 개념으로 동작
- 생성자, static 메서드, 필드 값 접근에 프록시 개념 불가
- 어드바이스 메서드에 매개변수로 선언
JoinPoint 인터페이스 기능
- JoinPoint.getArgs() - 전달된 인자 배열로 반환
- JoinPoint.getThis() - AOP 프록시 객체를 반환
- JoinPoint.getTarget() - AOP 적용 대상 객체(비즈니스 객체) 반환
- JoinPoint.getSignature() - 설명을 반환
- 클라이언트가 호출한 메서드의 시그니처 정보를 Signature 객체로 반환
- Signature
- String getName(), String toLongString(), String toShortString()
- JoinPoint.toString() - 설명 출력
ProceedingJoinPoint 인터페이스
- proceed() - 다음 어드바이스나 타깃 호출
Annotation을 활용한 AOP
@AspectJ
- 일반 java 클래스에 애너테이션으로 관점 선언하는 스타일
- 스프링은 AspectJ가 제공하는 라이브러리를 사용하여 애너테이션 해석
- AOP 런타임은 순수 스프링 AOP
사용
- 자동 프록시 빈에 대한 spring 지원 활성화하기
- XML
- <aop:aspectj-autoproxy/>
- Java
- @Configuration @EnableAspectJAutoProxy public class AppConfig{ ... }
Aspect 선언
<bean id="userAspect" class="...">
...
</bean>
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class [className]{
...
}
Pointcut 선언
- 어드바이스 실행되는 시기 제어
- Spring Bean의 메서드 실행과 일치
- 이름과 매개변수 포함하는 signature와 메서드 실행 결정하는 표현식으로 구성
- @Pointcut으로 표시
Advice 선언
- 포인트 컷과 일치하는 메서드 실행 전후에 실행