@Autowired
- required : 기본값은 true (따라서 못 찾으면 애플리케이션 구동 실패)
@Autowired라는 어노테이션이 없는데 어떻게 빈으로 등록이 된걸까?
어떤 빈이 되는 클래스의
생성자가 오직 하나만 있고 그 생성자의 매개변수 타입이 빈으로 등록이 되어있다면
@Autowired가 없더라도 자동으로 주입을 시켜준다.
Repository라는 interface 를 구현한 interface는 Spring Data JPA에서 .. LifeCycle .. 어쩌고 에서 bean으로 자동으로 등록해준다.... 그래서 따로 @Autowired라는 어노테이션이 없어도 bean으로 등록이 된다.
이렇게 되면 @Autowired 라는 어노테이션이 점점 사라진다고 한다. 이런식으로 코드를 짜면.
사용할 수 있는 위치
@Autowired / @Inject를 어디에 붙일까?
- 생성자 ( 어떠한 클래스에 반드시 필요한 의존성이다 하면 생성자)
빈이 없으면 인스턴스를 생성을 하지 못한다. ->
- Setter (만약 *어느 의존성에 대한 Setter를 가지고 있다면 Setter)
*어느 의존성 -> private final PetRepository pets;
- 필드 (Setter가 없다면 .. 하지만 @Autowired를 위해서 굳이 Setter를 만들어서까지 할 필요는 없다.)
내가 어떤 빈을 주입받았는지 확인 하고 싶을때
1. Runner를 하나 만들어 준다. (implements ApplicationRunner)
2. 빈을 주입 받으면, 주입 받은 빈의 클래스이름을 출력하게끔 해준다.
3. @Primary - 같은 타입의 빈이 여러개 일때
같은 타입의 빈이 여러개여도 @Primary로 등록해주면 그 빈이 주입이 된다.
아래는 실행했을때의 출력문 이다.
같은 타입의 빈이 여러개일때, 명확하게 표시를 안해주면 오류가 난다.
그리하여 이 오류에 대한 해결책은 다음과 같이 3가지가 있다.
- @Primary ("이 빈을 받을거다" 라고 마킹하는 용도)
- 해당 타입의 빈 모두 주입 받기
- @Qualify (빈 이름으로 주입)
@Primary
이 빈을 주입 하도록 표시하는 용도.
@Qualifier (빈 이름으로 주입) *이 방법보단 @Primary가 더 안전하다.
필드에다가 어노테이션을 붙여준다.
@Autowired @Qualifier("빈의 이름")
해당 타입의 빈 모두 주입 받기
모든 타입의 빈을 주입 받으려면 위에 코드를 추가해주면 된다.
그러면 해당 타입의 모든 빈이 출력이 된다.
동작 원리
- BeanPostProcessor
- 새로 만든 빈 인스턴스를 수정할 수 있는 라이프 사이클 인터페이스
- AutowiredAnnotationBeanPostProcessor extends BeanPostProcessor
- 스프링이 제공하는 @Autowired @Value 애노테이션 그리고 JSR-330의 @Inject애노테이션을 지원하는 애노테이션 처리기
출처 : http://blog.naver.com/PostView.nhn?blogId=edy5016&logNo=221280377077
결론부터 말하자면, @Autowired 애노테이션은 BeanPostProcessor라는 라이프 사이클 인터페이스의 구현체인 AutowiredAnnotationBeanPostProcessor에 의해 의존성 주입이 이루어진다.
BeanPostProcessor는 빈의 initializing(초기화) 라이프 사이클 이전, 이후에 필요한 부가 작업을 할 수 있는 라이프 사이클 콜백이다.
그리고 BeanPostProcessor의 구현체인 AutowiredAnnotationBeanPostProcessor가 빈의 초기화 라이프 사이클 이전, 즉 빈이 생성되기 전에 @Autowired가 붙어있으면 해당하는 빈을 찾아서 주입해주는 작업을 하는 것이다.
위의 빈 라이프 사이클을 보면 12. 빈 초기화 이전, 이후를 BeanPostProcessors가 감싸고 있는 것을 볼 수 있다.
AutowiredAnnotationBeanPostProcessor는 하나의 빈으로써 spring IoC 컨테이너에 등록되어 있다.
BeanFactory(ApplicationContext)는 BeanPostProcessor 타입의 빈 = AutowiredAnnotationBeanPostProcessor 빈을 꺼내 일반적인 빈들 = @Autowired로 의존성 주입이 필요한 빈들에게 @Autowired를 처리하는 로직을 적용한다.
12단계에는 사실상 이미 빈들이 주입이 되었기 때문에 사용 할 수가 있게된다.
@Service
public class EventLService {
@Autowired
MyBookRepository myBookRepository;
@PostConstruct
public void setup(){
System.out.println(myBookRepository.getClass());
}
}
출력이 되는 위치가 Runner와는 다르다. Spring-boot가 지원하는 ApplicationRunner는 applicaion이 완전히 구동이 됐을때, 그 다음에 처리가 되는 건데, 이 @PostConstruct 라이프 사이클 같은 경우에는 application 구동중(12 단계)에 찍히게 된다.
BeanFactory가 자신 안에 등록되어있는 BeanPostProcessors를 찾게 되고, 그 구현체 중 AutowiredAnnotaionBeanPostProcessor를 각 빈들에게 적용을 시키게 된다. (잘 이해가 안되지만..)
- AutowiredAnnotationBeanPostProcessor 가 빈으로 등록되어있는지 직접 꺼내서 출력해보자.
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext applicationContext;
@Override
public void run(ApplicationArguments args) throws Exception {
AutowiredAnnotationBeanPostProcessor bean = applicationContext.getBean(AutowiredAnnotationBeanPostProcessor.class);
System.out.println(bean);
}
}
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@43c87306