#참고도서: '스프링 프레임워크 첫걸음' (키노시타 마사아키, 위키북스)
03장: 스프링 프레임워크의 핵심 기능 알아보기
1. 의존성 주입(DI)
- 의존하는 부분을 외부에서 주입하는 것
1) 클래스 의존(구현 의존)
- '사용하는 객체' 클래스에서 '사용되는 객체' 클래스의 타입을 직접 지정해 버리면 '사용되는 객체' 클래스를 변경할 경우 이를 이용하고 있는 곳을 모두 수정해야 함
- 수정할 부분이 늘어나면 실수가 발행할 위험과 시간이 늘어남
2) 인터페이스 의존
- 참조를 받는 유형으로 사용할 수 있으므로 변수의 이름을 변경하지 않아도 됨
- 인터페이스가 선언된 메서드를 이용하면 클래스가 바뀌어도 메서드명을 변경하지 않아도 됨
- 클래스 의존보다 인터페이스 의존을사용하는 것으로 수정할 곳을 줄일 수 있음
2. 관점 지향 프로그래밍(AOP)
1) 중심적 관심사(Primary Concern)
- 실현해야 할 기능을 나타내는 프로그램
2) 횡단적 관심사(Crosscutting-Concerns)
- 본질적인 기능은 아니지만 품질이나 유지보수 등의 관점에서 반드시 필요한 기능을 나타내는 프로그램
- 예외처리, 로그 정보 화면이나 파일 등으로 출력 처리, 데이터베이스의 트랜잭션 제어 등
3. DI 컨테이너 다섯 가지 규칙
1) 인터페이스를 이용하여 의존성을 만든다
- 의존하는 부분에 인터페이슬르 이용한다는 것
2) 인스턴스를 명시적으로 생성하지 않는다
- 인스턴스 생성에 new 키워드를 사용하지 않는다는 것
3) 어노테이션을 클래스에 부여한다 & 4) 스프링 프레임워크에서 인스턴스를 생성한다
- 인스턴스를 생성하려는 클래스에 인스턴스 생성 어노테이션을 부여한다는 것
- @Controller: 인스턴스 생성 지시, 스프링 MVC를 이용할 때 컨트롤러에 부여
- @Service: 인스턴스 생성 지시, 트랜잭션 경계가 되는 도메인(서비스) 기능에 부여
- @Repository: 인스턴스 생성 지시, 데이터베이스 액세스(리포지토리) 기능에 부여
- @Component: 위 용도 이외의 클래스에 부여
5) 인스턴스를 이용하고 싶은 곳에 어노테이션을 부여한다
- 스프링 프레임워크에 의해 생성된 인스턴스를 이용하는 클래스에 참조를 받는 필드를 선언하고 필드에 @Autowired 어노테이션 부여
4. DI 프로그램 만들기
// 인사 인터페이스
public interface Greet {
// 인사하기
void greeting();
}
// Greet 구현 클래스, 아침 인사 하기
@Component
public class MorningGreet implements Greet{
@Override
public void greeting(){
System.out.println("-------------");
System.out.println("좋은 아침입니다");
System.out.println("-------------");
}
}
//스프링부트 시작 클래스
@SpringBootApplication
public class BookstudyApplication {
//메인 메서드: 자신의 execute 메서드를 호출하도록 작성
public static void main(String[] args) {
SpringApplication.run(BookstudyApplication.class, args)
.getBean(BookstudyApplication.class).execute();
}
//주입하는 곳(인터페이스)
@Autowired
Greet greet;
//실행 메서드
private void execute(){
greet.greeting();
}
}
[소스코드 설명]
- 스프링 프레임워크는 기동 시 컴포넌트 스캔에 의해 MorningGreet 클래스에 @Component 어노테이션이 부여되어 MorningGreet 인스턴스가 생성됨
- @Autowired 어노테이션에 따라 MorningGreet 클래스의 인스턴스가 클래스의 greet 필드에 주입되어 실행되면 MorningGreet 클래스의 getting 메서드가 실행됨
[요약]
- 스프링 프레임워크는 임의로 구현한 클래스를 인스턴스화하는 기능을 제공(DI 컨테이너)
- 스프링 프레임워크를 사용하는 애플리케이션은 인스턴스를 명시적으로 생성하지 않음(new 키워드를 사용하지 않음)
- 정해진 어노테이션(@Component)을 클래스에 부여하는 것으로 스프링 프레임워크가 인스턴스를 생성
- 생성된 인스턴스를 사용하고 싶은 부분에서 필드를 준비하고 주석(@Autowired)을 부여하면 스프링 프레임워크가 인스턴스가 필요한 것으로 판단하고 인스턴스를 주입
- 인스턴스를 이용해서 의존성을 만들고 DI를 사용하여 '사용되는 객체' 클래스를 변경하는 경우 '사용하는 객체' 클래스의 수정 없이 변경할 수 있음
5. 어노테이션

1) 도메인 주도 설계 레이어
- Application Layer: 클라이언트와 데이터의 입출력을 제어하는 레이어
- Domain Layer: 애플리케이션의 중심이 되는 레이어로서 업무 처리를 수행하는 레이어
- Infrastructure Layer: 데이터베이스에 대한 데이터 영속성 등을 담당하는 레이어
2) 레이어별 인스턴스 생성 어노테이션
- @Controller: 애플리케이션 레이어의 컨트롤러에 부여
- @Service: 도메인 레이어의 업무 처리에 부여
- @Repository: 인프라 레이어의 데이터베이스 액세스 처리에 부여
- @Component: 하위 로직을 처리할 때 사용
6. 관점 지향 프로그래밍(AOP, Aspect Oriented Programming)
- 프로그램을 '중심적 관심사'와 '횡단적 관심사' 2개의 요소로 구성되어 있다고 생각
- AOP는 본질적인 기능은 아니나 꼭 필요한 기능인 횡단적 관심사를 분리함으로써 기존 코드를 수정하지 않아도 프로그램 중에 특정 기능(공통 처리)을 추가할 수 있음
1) AOP 고유 용어
- Advice, Aspect, JoinPoint, Pointcut, Interceptor, Target
2) 어드바이스의 다섯 가지 어노테이션 종류
- @Before, @AfterReturning, @AfterThrowing, @After, @Around
3) 포인트컷 식
- 직접 어드바이스를 만드는 경우 패키지, 클래스, 메서드 등 어드바이스 삽입 대상을 조건으로 지정할 수 있음
- 지정하는 조건 방법에는 포인트 컷 사용
- execute(반환값 패키지.클래스.메서드(인수))
package me.yuan.bookstudy.used.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
@Aspect //어드바이스를 기술하는 클래스
@Component //인스턴스 생성
public class SampleAspect {
@Before("execution(* me.yuan.bookstudy.used.*Greet.*(..))") //메서드 실행 전에 호출
public void beforeAdvice(JoinPoint joinPoint) {
//시작 부분 표시
System.out.println("=== Before Advice ===");
//날짜를 출력
System.out.println(new SimpleDateFormat("yyyy/MM/dd").format(new java.util.Date()));
//메서드 이름 출력
System.out.println(String.format("메서드:%s", joinPoint.getSignature().getName()));
}
@After("execution(* me.yuan.bookstudy.used.*Greet.*(..))") //메서드 실행 후에 호출
public void afterAdvice(JoinPoint joinPoint) {
//시작 부분 표시
System.out.println("=== After Advice ===");
//날짜를 출력
System.out.println(new SimpleDateFormat("yyyy/MM/dd").format(new java.util.Date()));
//메서드 이름 출력
System.out.println(String.format("메서드:%s", joinPoint.getSignature().getName()));
}
@Around("execution(* me.yuan.bookstudy.used.*Greet.*(..))") //메서드 실행 전후에 호출
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
//시작 부분 표시
System.out.println("=== Arou줌d Advice ===");
System.out.println("*** 처리전 ***");
//지정한 클래스의 메서드 실행
Object result = joinPoint.proceed();
System.out.println("*** 처리후 ***");
//반환값을 돌려줄 필요가 있는 경우에는 Object 타입의 반환값을 돌려줌
return result;
}
}
4) Around Advice와 다른 어드바이스와의 차이
- 인수는 ProceedingJoinPoint 인터페이스 타입을 지정
- 어드바이스 중에서 ProceedingJoinPoint 인터페이스의 proceed() 메서드를 호출
- 어드바이스 적용 대상의 메서드를 임의의 타이밍으로 호출할 수 있으므로 전후로 다양한 처리가 가능
7. @Transactional
- 트랜잭션 관리에 사용하는 어노테이션
- 데이터베이스 액세스 처리 메서드가 정상 종료하면 트랜잭션을 커밋하고 예외가 발생하면 롤백
'zb_backend19' 카테고리의 다른 글
[북스터디] 스프링 프레임워크 첫걸음 5주차 (0) | 2024.02.19 |
---|---|
[북스터디] 스프링 프레임워크 첫걸음 4주차 (0) | 2024.02.19 |
[북스터디] 스프링 프레임워크 첫걸음 2주차 (0) | 2024.02.01 |
[북스터디] 스프링 프레임워크 첫걸음 1주차 (0) | 2024.01.29 |
자료구조 1 Page 노트 정리_Heap 힙 (0) | 2023.11.21 |