본문 바로가기

Java/Spring Framework

Autowired & Component

반응형

Spring boot 프로젝트에서 여러 annotation이 사용됩니다.

이번 글에서는 annotation에 대해서 정리를 진행하도록 하겠습니다.

 

객체의 의존성을 가지는 부분에 해당 어노테이션을 사용하여 쉽게 의존성을 주입할 수 있습니다.

의존 객체를 주입하는 방법은 스프링 설정파일에서 <constructor-arg> 혹은 <property> 태그로 의존 객체를 명시하는 방법이 있습니다. 

의존객체 자동 주입(Automatic Dependency Injection)은 스프링 컨테이너가 자동으로 의존 대상 객체를 찾아 해당 객체에 필요한 의존성을 주입해줍니다.

이를 구현하는 방법은 @Autowired 와 @Resource를 통해 구현가능합니다. 

 

1. Autowired

1.1 설명

@Autowired는 주입하려하는 Bean의 타입이 일치하는지 찾고 의존성 주입을 합니다.

따라서 주입하려는 객체는 Bean으로 등록해둬야합니다!! @Repository, @Annotation 

만약 타입이 존재하지 않거나 일치하는 타입이 여러개인 경우 @Autowired에 위치한 "속성명"이 일치하는 bean을 컨테이너에서 찾습니다.

그리고 이름이 없는 경우 @Qulifier 어노테이션 유무를 찾아 그 어노테이션이 붙은 속성에 의존성을 주입합니다.

타입 - 이름 - Qualifier 순으로 찾음

 

찾는 Bean이 없거나 의존성 주입이 불가한 경우 error 가 발생하는데 이때 필수적용을 false 로 바꿔 의존성을 optional로 바꿔주면 에러를 해결할 수 있습니다. 

위의 예처럼 처리하면 BookRepository 는 의존성 주입은 되지 않은 채로 Bean이 등록됩니다. 

 

 

1.2 사용할 수 있는 위치

  • 생성자(스프링 4.3 부턴 생략 가능) - 해당하는 bean이 없다면 인스턴스가 무조건 생성되지 않습니다
  • setter - 선택적인 경우에는 required = false로 지정하면 됩니다. 기본값이 true 입니다.
  • field

생성자에 사용
setter에 사용
field에 사용

 

 

1.3 발생할 수 있는 에러

- 해당 타입의 빈이 여러개인 경우

위 에러 문구를 보시면 2개가 발견됐고 어느것을 해야하는지 모르겠다고 작성되어 있습니다. 

해결책!

이에 대한 해결책은

1 )) @Primary 를 이용해 주로 사용할 Bean을 등록해둡니다.

@Primary 사용

2 )) @Qulifier 를 사용해 무엇을 원하는지 마킹해줍니다. 괄호안에는 빈의 id를 적는데 일반적으로는 클래스 이름을 작성하면 됩니다.

@Qulifier 사용

3 )) 모든 Bean을 받습니다.

@Autowired

List<BookRepository> bookRepository;

 

번외)) bean의 이름을 클래스 이름과 동일하게 줘도 됩니다. 그러면 해당 이름으로 빈을 등록하게 됩니다.

하지만, @primary 를 이용하는 방법이 가장 깔끔합니다.

 

동작 원리

BeanPostProcessor의 구현체에 의해 동작하게 됩니다.

BeanPostProcessor 란 bean의 인스턴스를 만든 다음에 bean 에게 부가적인 작업을 수행할 수 있는 인터페이스입니다.

부가적인 작업을 구현하는 방법은 @PostContruct 를 이용하는 방법, 혹은 InitializingBean 인터페이스를 구현한 후 afterPropertiesSet() 메소드를 구현하는 방법이 있습니다.

 

**빈라이프 사이클

빈이 생성된 직후 수행됨

 

2. Component & ComponentScan

Spring boot Application 에서 사용하는 @SpringBootAppplication은 @ComponentScan이 있습니다.

SpringBootApplication

ComponentScan은 해당 어노테이션이 있는 class부터 시작해 같은 패키지안, 하위 패키지 순서대로 scan을 수행합니다. 

하지만, 패키지밖에 있는 것은 되지 않습니다. 따라서 Bean으로 등록되지 않아 @Autowired를 수행할 수 없습니다.

외부 패키지여서 Autowired 불가합니다! 에러발생!

 

또한 ComponentScan을 한다고 해서 모든 Annotation을 Bean으로 등록하는 것은 아닙니다.

이는 excludeFilters 안에 작성하여 걸리는 것이 있기 때문입니다.

 

 

SpringBootApplication

앞서 보았던 위 이미지에서는 TypeExcludeFilter 와 AutoConfigurationExcludeFilter 로 걸려주고 있습니다. 

이렇듯 어디를 scan할지와 어디를 걸러줄지를 설정해줍니다.

 

Singleton Scope의 Bean들은 모두 초기에 생성하므로 초기 구동시간이 오래걸릴 수 있습니다.

혹시 외부 패키지의 Bean을 등록하고 싶다면 아래와 같이 직접 주입해 줄 수 있습니다.

이렇게 사용하게 되면 어플리케이션 구동시에 성능상의 이점이 있습니다.

Function을 이용한 빈등록

Functional 한 방법이 성능상의 이점이 있긴 하지만 Component-scan 방법을 이용하는 것이 설정 파일을 줄일 수 있습니다. Component scan 방식이 일일이 등록하는 번거로움을 줄일 수 있기 때문에 추천드립니다.

반응형

'Java > Spring Framework' 카테고리의 다른 글

Environment  (0) 2020.10.24
Scope  (0) 2020.10.19
기본 개념 Spring  (0) 2020.10.15
RESTful API 웹서비스 테스트  (0) 2020.03.11
REST에서 CRUD 구현  (0) 2020.03.06