⚙️Backend/SPRING
[Spring Boot] 스프링 의존성 주입 @Autowired, @Resource, @Inject
soonybutter
2024. 12. 14. 13:04
스프링 의존성 주입 @Autowired, @Resource, @Inject (Java Spring Dependency Injection)
의존성 주입은 객체를 직접 생성하지 않고 @Service을 이용하여 class annotation으로 달아주면 스프링은 beanFactory에 담아 두고 사용하는 곳에 @Autowired을 사용하는 곳에 해당 bean을 찾아 주입시켜 객체를 사용할 수 있게 도와준다.
1. @Autowired
@Autowired는 주입하려고 하는 객체의 타입이 일치하는 객체를 loc 컨테이너 안에 존재하는 Bean을 자동으로 주입한다.
주입 방법은 3가지가 있다.
필드 주입 (Field Injection)
필드에 @Autowired 어노테이션을 붙여 주면 자동으로 의존성이 주입된다. 매우 간단하며 예제로 많이 사용되는 방법이다.
public class TestController { @Autowired private InjectSampleService injectSampleService; @GetMapping("/persion") public List<Person> getPersions(@RequestParam(name = "name") String name) { return injectSampleService.query(name); } }
생성자 주입 (Constructor Injection)
단일 생성자인 경우 @Autowired 어노테이션을 붙이지 않아도 되지만 생성자 2개 이상일 경우에는 어노테이션을 꼭 붙여주어야 한다.
public class TestController { private InjectSampleService injectSampleService; @Autowired // spring 4.3 버전 이상부터는 생략 가능 public TestController(InjectSampleService injectSampleService) { this.injectSampleService= injectSampleService; } @GetMapping("/persion") public List<Person> getPersions(@RequestParam(name = "name") String name) { return injectSampleService.query(name); } }
세터 주입 (Setter Injection)
메서드 이름이 세터 네이밍 패턴(setXXXX)이 아니어도 동일한 기능을 하지만 일관성과 명확한 코드를 만들기 위해서
정확한 이름을 사용하는 것을 추천한다.
public class TestController { private InjectSampleService injectSampleService; @Autowired // spring 4.3 버전 이상부터는 생략 가능 public void setInjectSampleService(InjectSampleService injectSampleService) { this.injectSampleService= injectSampleService; } }
여기서 알아야 할 내용은 필드 주입을 사용하면 다음과 같이 경고가 발생한다.
Spring Team recommends: “Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies”.
필드 주입을 사용하지 말고 생성자 주입을 사용하라는데 생성자 주입을 권장하는 이유는 다음과 같다.
https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection
- 순환 참조 방지 (A가 B를 참조하고 B가 A를 참조할 때 발생될 수 있는 문제)
- 테스트에 용이
- final 선언 가능
- 오류 방지 (불변(immutable) 객체 또는 null 방지 가능)
Qualifier 어노테이션
동일한 타입의 빈 객체가 여러개 정의되어 있을 경우,
우선적으로 사용할 빈 책체의 <bean> 태그 하위에 <qualifier>태그를 설정하여 특정 빈을 주입할 수 있게 한다.
<bean id="testInject1" class="com.example.demo.services" > <qualifier value="qualifierTest"/> </bean> <bean id="testInject2" class="com.example.demo.services" />
public class WordRegisterServiceUseAutowired { @Autowired @Qualifier("qualifierTest") private InjectSampleService injectSampleService; @GetMapping("/persion") public List<Person> getPersions(@RequestParam(name = "name") String name) { return injectSampleService.query(name); } }
2. @Resource
@Resource는 주입하려고 하는 객체의 이름(id)이 일치하는 객체를 자동으로 주입하며 필드, Setter에 붙일 수 있지만 생성자에는 붙일 수 없다. @Autowired와 마찬가지로 반드시 기본 생성자가 정의되어 있어야 한다.
의존성 설정
프로젝트에서 사용하기 위해 javax.annotation-api 의존성을 추가한다.
<dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
import javax.annotation.Resource; public class WordRegisterServiceUseResource { @Resource private WordDao wordDao; public WordRegisterServiceUseResource() { } }
import javax.annotation.Resource; public class WordRegisterServiceUseResource { private WordDao wordDao; public WordRegisterServiceUseResource() { } @Resource public WordRegisterServiceUseResource(WordDao wordDao) { this.wordDao = wordDao; } }
3. @Inject
@Inject는 @Autowired와 유사하게 주입하려고 하는 객체의 타입이 일치하는 객체를 자동으로 주입한다.
의존성 설정
프로젝트에서 사용하기 위해 javax.inject 의존성을 추가한다.
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
필드 주입 (Field Injection)
import javax.inject.Inject; public class WordRegisterServiceUseAutowired { @Inject private WordDao wordDao; public WordRegisterServiceUseAutowired() { } }
생성자 주입 (Constructor Injection)
import javax.inject.Inject; public class WordRegisterServiceUseAutowired { private WordDao wordDao; @Inject public WordRegisterServiceUseAutowired(WordDao wordDao) { this.wordDao = wordDao; } }
import javax.inject.Inject; public class WordRegisterServiceUseAutowired { private WordDao wordDao; public WordRegisterServiceUseAutowired() { } @Inject public void setWordDao(WordDao wordDao) { this.wordDao = wordDao; } }
Named 어노테이션
@Autowired의 @Qualifier 와 비슷한 역할을 하는게 @Inject에서의 @Named이다.
@Qualifier와 달리 @Named에는 bean id 을 지정하므로
@Autowired, @Qualifier를 사용할때에 비해 XML 설정 파일이 다소 짧아진다는 특징이 있다.
XML 설정 파일
<Qualifier> 태그가 필요한 @Qualifier와 달리 @Named는 XML 설정 파일에 추가적으로 설정할 것이 없다.
<bean id="wordDao1" class="com.word.dao.WordDao"/> <bean id="wordDao2" class="com.word.dao.WordDao"/> <bean id="wordDao3" class="com.word.dao.WordDao"/>
자바 코드
@Named에 빈 이름(id)를 지정한다.
import javax.inject.Inject; import javax.inject.Named; public class WordRegisterServiceUseInject { @Inject @Named("wordDao1") private WordDao wordDao; public WordRegisterServiceUseInject() { } }
*공부용 기록입니다.