Spring Framework

Spring Framework의 DI (Dependency Injection, 의존성 주입)과 AOP (Aspect Oriented Programming)

데굴데굴. 2020. 2. 27. 20:43

인프런 백기선님의 스프링  프레임워크 입문을 듣고 필기한 내용입니다:)

 

DI

Spring의 IoC 컨테이너 자체를 꺼내오는 법 (쓸 일 별로 없음)

@Autowired
ApplicationContext applicationContext;

 

컨테이너에서 빈 가져와 사용하는 법

applicationContext.getBean(_______.class)

 

 

의존성 주입 방법

 

1. 생성자 (1순위)

생성자가 하나만 있고 생성자의 매개변수 타입이 빈으로 등록되어 있으면 @Autowired가 없어도 빈을 주입해준다.

이 클래스에서 꼭 필요한 클래스라면 생성자 방법을 추천한다고 하셨다.

private final VisitRepository visits;
private final PetRepository pets;

public VisitController(VisitRepository visits, PetRepository pets) {
    this.visits = visits;
    this.pets = pets;
}

 

2. 필드 (3순위)

생성자 방법을 사용할 수 없고 setter도 없을 때 사용하는 것을 추천하셨다.

@Autowired
private final VisitRepository visits;
@Autowired
private final PetRepository pets;

 

3. setter (2순위)

생성자 방법을 사용할 수 없고 클래스에 setter가 존재할 때 추천하는 방법.

setter가 필요 없을 때 굳이 setter를 만들어서 이 방법을 쓸 필요까지는 없다.

처음에만 의존성을 주입하면 되는 클래스에 setter를 굳이 만들 필요는 없으니까.

private final VisitRepository visits;
private final PetRepository pets;

@Autowired
public void setVisitRepository(VisitRepository visits) {
	this.visits = visits;
}

@Autowired
public void setPetRepository(PetRepository pets) {
	this.pets = pets;
}

 

AOP

예제 - 메소드의 실행시간 로깅을 위한 애노테이션

 

LogExecutionTime.java

@Target(ElementType.METHOD) // 이 애노테이션을 어디 붙일 건지
@Retention(RetentionPolicy.RUNTIME) // 언제까지 이 코드를 유지할 건지
public @interface LogExecutionTime { // 메소드 처리시간 로깅할 코드 작성

}

애노테이션은 그냥 마커일 뿐이고 아무 것도 하지 못한다.

 

LogAspect.java

@Component
@Aspect // 모듈화
public class LogAspect { // 애노테이션 달았을 때 실제 작동할 클래스. 빈이어야 함
	
    Logger logger = LoggerFactory.getLogger(LogAspect.class);
    
    @Around("@annotation(LogExecutionTime)") // 타겟 메소드를 감싸서 특정 Advice를 실행하겠다는 의미
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) {
    	StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        Object ret = joinPoint.proceed(); // 원래 실행할 메소드 호출 자체를 감싼다는 의미
        
        stopWatch.stop();
        logger.info(stopWatch.prettyPrint()); // info 레벨로 찍기
        
        return ret;
    }
}

실제로 실행되는 것은 이 파일의 코드

 

 

 

@Transactional

  • 트랜잭션을 처리하는 공통 코드가 적용되도록 함 (try catch 형식으로, 문제 생겼을 때 rollback하는 내용)
  • spring data jpa가 제공하는 모든 메소드에는 기본적으로 @Transactional이 모두 적용되어 있다. (생략되어 있더라도)
  • @Transactional(readOnly = true) 등이 붙어있는 건 기존의 @Transactional이 처리하는 코드를 오버라이딩 해서 리드온리 옵션을 추가한 것 뿐이다.