스프링의 철학은 POJO(Plain Old Java Object)로 스프링 프레임워크를 나중에 걷어내더라도 코드가 정상적으로 동작할 수 있도록 프렘웍에 의존적인 코드를 작성하지 않는 것인데 그런 의미에서 @Autowired 보다는 다른 방법을 이용하는 것이 좋다고 공부했었다. 그럼 왜 @Autowired 어노테이션을 이용한 DI를 지양해야 하는지 @Autowired의 원리에 대해서 알아보자.
@Autowired 애노테이션을 이용하면 설정자 메서드를 이용하지 않고도 스프링 프레임워크가 설정 파일을 통해 설정자 메서드 대신 속성을 주입해 준다. (스프링 설정 파일을 보고 자동으로 속성의 설정자 메서드에 해당하는 역할을 해주겠다는 의미)
@Autowired는 type 기준으로 매칭을 하기 때문에 같은 타입을 구현한 클래스가 여러 개 있다면 그때 bean 태그의 id로 구분해서 매칭한다. (id 매칭 보다 type 매칭이 우선이다)
- @Resource의 경우 type과 id 가운데 매칭 우선순위는 id가 높다. id로 매칭할 빈을 찾지 못한 경우 type으로 매칭할 빈을 찾게 된다.
자바 표준인 @Resource를 쓰는 것이 유리(내가 공부했던 책의 필자의 생각)
@Autowired는 type을 기준으로 매칭하기 때문에 같은 타입을 구현한 클래스가 여러 개 있다면 단일 빈을 매칭하기에 부적절합니다.
How to solve such problem:
슈퍼 클래스가 같은 두 개 이상의 서브 클래스들을 구별하기 위해서 스프링 컨텍스트가 서브 클래스를 찾을 수 있는 특정한 이름을 지정해야 합니다.
객체가 생성되면, 객체 변수에 할당될 때 주입됩니다.
컨테이너가 초기화되면, post processor의 초기화가 나머지 사용자 정의 빈(사용자 정의 서비스, 컨트롤러 등등..)의 초기화들보다 먼저 일어난다. 사용자 정의 빈 초기화는 AbstractApplicationContext
의 finishBeanFactoryInitialization 메서드에 의해 실행된다.
FinishBeanFactory Initialization (beanFactory)
– > beanFactory. preInstantiate Singletons ()
– > getBean (beanName)
– > doGetBean (beanName) > to line 317 of AbstractBeanFactory (beanName, mbd, args) to create bean instances
– > to line 503 of AbstractBeanFactory CreateBean (beanTombuse, args)
– > and then to line 533 of AbstractBeanFactory AutowireableB In line 543 of eanFactory, instance Wrapper = createBeanInstance (beanName, mbd, args) has created the bean instance, except that instance Wrapper is a wrapped bean whose properties have not yet been assigned the actual value
– > and then comes to line 555, applyMergedBeanDefinitionPostProcessors (mbd, beanType, beanName).
위의 흐름은 모든 뒤따라오는 빈들을 배치하는 것입니다. 프로세서는 그것을 꺼내 beanName 이라는 클래스의 변수를 InjectionMetadata의 주입된 Elements 세트에 캡슐화하고, 나중에 취득해, 인스턴스를 1개씩 작성하고, reflection을 통해 대응하는 클래스에 주입시킵니다.
남은 내용은 내가 생각했을 때 너무 DeepDive 하는 느낌이 들어 링크를 옮긴다. 나중에 궁금증이 더 생길 때 찾아보기로..
Spring Source Analysis: @Autowire Annotation Principle Analysis - Develop Paper
요약을 하자면 컨테이너가 시작되고 객체에 값을 할당할 때 @Autowired 어노테이션을 만나면 post-processor 매커니즘을 사용하여 애트리뷰트의 인스턴스를 생성한다. 그런다음 reflection 매커니즘을 사용하여 인스턴스화된 속성을 객체에 할당합니다.
@Autowired를 통해 DI 코드가 깔끔해 보이는데 Field Injection을 지양하라고 하는 이유는 뭘까?
<원문 참조>
Spring Source Analysis: @Autowire Annotation Principle Analysis - Develop Paper