@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);
}
동작 원리
- @ComponentScan은 스캔할 패키지와 애노테이션에 대한 정보
- 실제 스캐닝은 ConfigurationClassPostProcessor 라는 BeanFactoryPostProcessor 에
의해 처리 됨.
빈의 스코프
스코프
- 싱글톤
애플리케이션에서 한 개만 선언되어 사용됨. - 프로토타입
매번 새롭게 만들어서 사용해야 하는 빈
프로토타입 빈이 싱글톤 빈을 참조하면?
- 싱글톤은 의도한 대로 같은 ID를 가지며 한 번 동일한 빈을 사용하게 된다.
싱글톤 빈이 프로토타입 빈을 참조하면?
- 싱글톤 내의 프로토타입이 항상 새롭게 생성이 된다. (의도치 않은 동작)
- 프록시모드를 사용하여 업데이트를 할 수 있음.
(scoped-proxy, Obejct-Provider, Provider - 표준)
'노력 > Spring Boot' 카테고리의 다른 글
스프링 프레임워크 핵심 기술 - (3) (0) | 2021.11.28 |
---|---|
스프링 프레임워크 핵심 기술 - (1) (0) | 2021.11.19 |
IntelliJ에서의 Spring boot 테스트 프로젝트 - (1) (0) | 2021.05.29 |
Spring Boot와 Spring의 디렉터리 구조 차이점 그리고 Entity (0) | 2020.01.25 |