본문 바로가기

노력/Spring Boot

스프링 프레임워크 핵심 기술 - (2)

@Autowire

필요한 의존 객체의 "타입"에 해당하는 빈을 찾아 주입한다.

 

@Autowired

  • required: 기본값은 true (Autowired 주입하는 빈에 문제가 있는 경우 애플리케이션 구동 실패)

사용할 수 있는 위치

  • 생성자 (스프링 4.3부터는 생략도 가능)
  • 세터
  • 필드

경우의 수 (실패, 성공)

  • 해당 타입의 빈이 없는 경우
  • 해당 타입의 빈이 한 개인 경우
  • 해당 타입의 빈이 여러 개인 경우
    (빈 이름으로 시도 - 같은 이름 찾으면 해당 빈 사용, 같은 이름 못 찾으면 실패)

같은 이름으로 빈 주입을 사용하는 경우는 타입이 여러개 있는 것을 알고 있는 개발자만 이해하고 사용할 수 있을 것으로 보임. 새로운 개발자가 빈 주입을 할 때 혼란이 있을 것 같음.

// 주입할 때
@Autowired
SomeRepository doSomeRepository

// 각 Repository에서 같은 SomeRepository를 implements 함.
// 두 Repository가 SomeRepository의 이름을 가지고 있어 이름의 구분이 없었다면 에러 발생.
// ex.) SomeRepository someRepository
// 위 주입할 때 처럼 doSomeRepository처럼 직접 이름 구분을 해 주어서 사용할 수 있다.
@Repository
public interface SomeRepository {
}

@Repository
public class DoSomeRepository implements SomeRepository {
}

@Repository
public class DoOtherRepository implements SomeRepository {
}

같은 타입의 빈이 여러개 일 때

  • @Primary (만약 이렇게 사용한다면 기선님은 이 방법이 TypeSafe하기 때문에 추천)
    // 주입할 때
    @Autowired
    SomeRepository someRepository;
    
    // Primary로 같은 이름 중에 우선순위를 가진 빈을 주입
    // primary를 가진 DoSomeRepository가 someRepository에 주입됨.
    @Repository
    public interface SomeRepository {
    }
    
    @Repository @Primary
    public class DoSomeRepository implements SomeRepository {
    }
    
    @Repository
    public class DoOtherRepository implements SomeRepository {
    }​
  • 해당 타입의 빈 모두 주입 받기
    // SomeRepository 이름을 가진 빈들을 모두 주입
    @Autowired
    List<SomeRepository> someRepositories;​
  • @Qualifier (빈 이름으로 주입)
    @Autowired @Qualifier("doSomeRepository")
    SomeRepository someRepository​

동작원리 (세세한 원리까지는 확인이 필요)

  • 빈 라이프사이클
  • @PostContruct (빈 생성 이후에 실행되는 인터페이스)
  • BeanPostProcessor (AutowiredAnnotationBeanPostProcessor을 호출)
  • AutowiredAnnotationBeanPostProcessor extends BeanPostProcessor (Autowired가 가능하게 해주는 마법같은 프로세서, 이 빈은 자동으로 등록되어 있는 Bean)

@Component와 컴포넌트 스캔

@ComponentScan (Spring 3.1부터 도입)

ComponentScan을 붙이고 있는 Configuration 패키지를 스캔. 패키지 내의 Component를 빈으로 주입함.

Scan이 되지 않은 패키지는 빈으로 주입되지 않음.

 

@Component

  • @Repository
  • @Service
  • @Controller
  • @Configuration

 

펑션을 사용한 빈 등록 (Spring5 부터 추가된 function을 이용한 추가)

  • 애플리케이션 구동 시 ComponentScan이 잡아먹는 성능이 싫은 경우에는 이렇게 등록할 수도 있음.
  • 로직들을 함께 사용할 수 있다는 장점이 있음.

 

개인적으로는 한동안 쓸 일이 없는 방법으로 보임.

public static void main(String[] args) {
  new SpringApplicationBuilder()
    .sources(Demospring51Application.class)
    .initializers((ApplicationContextInitializer<GenericApplicationContext>)
      applicationContext -> {
      	applicationContext.registerBean(MyBean.class);
      })
  	.run(args);
}

 

동작 원리


빈의 스코프

스코프

  • 싱글톤
    애플리케이션에서 한 개만 선언되어 사용됨.

  • 프로토타입
    매번 새롭게 만들어서 사용해야 하는 빈

 

프로토타입 빈이 싱글톤 빈을 참조하면?

  • 싱글톤은 의도한 대로 같은 ID를 가지며 한 번 동일한 빈을 사용하게 된다.

 

싱글톤 빈이 프로토타입 빈을 참조하면?

  • 싱글톤 내의 프로토타입이 항상 새롭게 생성이 된다. (의도치 않은 동작)
  • 프록시모드를 사용하여 업데이트를 할 수 있음.
    (scoped-proxy, Obejct-Provider, Provider - 표준)

프록시 (https://en.wikipedia.org/wiki/Proxy_pattern)