2023. 12. 10. 20:37ㆍSpring Framework/Spring IoC
Spring의 @Autowired
및 JSR-330 @Inject
완벽 정리 🚀
Spring에서는 @Autowired
를 사용하여 빈(Bean)의 의존성을 자동으로 주입할 수 있습니다.
또한, JSR-330(javax.inject.Inject
)을 사용하면 Spring에 종속되지 않고 표준적인 방식으로 DI(Dependency Injection)를 수행할 수도 있습니다.
📌 1️⃣ @Autowired
및 @Inject
개념과 주요 특징
✅ Spring IoC 컨테이너가 적절한 빈을 찾아 자동으로 주입
✅ 생성자, 필드, 세터, 일반 메서드에 적용 가능
✅ 같은 타입의 빈이 여러 개 존재하면 충돌 발생 가능 → @Qualifier
또는 @Primary
사용
✅ Spring 4.3+ 부터 생성자가 1개만 있는 경우 @Autowired
생략 가능
✅ JSR-330(@Inject
)을 사용하여 Spring 의존성을 제거 가능
✅ @Nullable
, Optional<T>
을 사용하여 주입할 빈이 없을 경우 null 처리 가능
✅ Self Injection (자기 참조 주입) 지원 → 우선순위가 가장 낮으며, 최후의 수단으로 사용해야 함
✅ Spring @Autowired
vs 표준 @Inject
@Autowired
는@Primary
,required=false
등 추가 기능 제공@Inject
는 Java 표준이므로 Spring 이외의 DI 프레임워크에서도 사용 가능
✅ Spring은@Autowired
,@Inject
,@Value
,@Resource
를BeanPostProcessor
를 통해 처리- 이 때문에
BeanPostProcessor
나BeanFactoryPostProcessor
내부에서는 사용할 수 없음 BeanPostProcessor
자체는 XML 설정이나@Bean
을 통해 명시적으로 설정해야 함
📌 2️⃣ @Autowired
vs @Inject
비교
어노테이션 | 패키지 | 설명 |
---|---|---|
@Autowired |
org.springframework.beans.factory.annotation |
Spring이 제공하는 자동 주입 기능 |
@Inject |
javax.inject (jakarta.inject ) |
Java 표준의 의존성 주입(DI) |
✔ 둘 다 기본적으로 동일한 기능을 수행하지만, 차이점이 있음
@Autowired
는@Primary
,required=false
등의 추가 기능을 제공@Inject
는 Java 표준이므로 Spring이 아닌 다른 DI 프레임워크에서도 사용 가능
✅ @Inject
사용 예제
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Inject
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
}
✅ @Named
는 @Component
와 같은 역할을 하며, @Inject
는 @Autowired
와 동일한 역할을 수행
📌 3️⃣ @Autowired
적용 방법
✅ 1) 생성자 주입 (Constructor Injection)
가장 권장되는 방식이며, 불변성(immutability) 보장 및 테스트 용이
@Component
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
}
✅ Spring 4.3 이후, 생성자가 1개일 경우 @Autowired
생략 가능
@Component
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
// Spring 4.3+에서는 @Autowired 생략 가능
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
}
✅ 2) 세터 주입 (Setter Injection)
의존성을 선택적으로 주입할 때 유용하지만, 불변성이 보장되지 않음
@Component
public class MovieRecommender {
private MovieFinder movieFinder;
// 세터 주입
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
✅ 3) 필드 주입 (Field Injection)
가장 간단하지만 테스트 및 유지보수 어려움 → 권장되지 않음
@Component
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
}
🚨 필드 주입의 문제점
- 외부에서 직접 주입할 방법이 없어 테스트하기 어려움
- DI 프레임워크(SPRING)에 강하게 결합됨 → POJO 객체로 활용 어려움
- 생성자 주입을 우선적으로 사용하는 것이 바람직함
📌 4️⃣ @Autowired
충돌 해결 (@Primary
, @Qualifier
)
✅ 1) @Primary
(우선순위 설정)
같은 타입의 빈이 여러 개 있을 때 primary 빈을 지정
@Component
@Primary
public class ActionMovieCatalog implements MovieCatalog {
// ...
}
@Component
public class ComedyMovieCatalog implements MovieCatalog {
// ...
}
✅ 2) @Qualifier
(특정 빈 선택)
@Primary
보다 더 명확하게 특정 빈을 지정할 때 사용
@Component
public class MovieService {
private final MovieCatalog movieCatalog;
@Autowired
public MovieService(@Qualifier("comedyMovieCatalog") MovieCatalog movieCatalog) {
this.movieCatalog = movieCatalog;
}
}
📌 5️⃣ Self Injection (자기 참조 주입)
Spring 4.3+ 부터 @Autowired
는 자기 참조(Self Injection) 를 지원합니다.
📌 하지만 자기 주입(Self Injection)은 우선순위가 가장 낮으며, 최후의 수단으로 사용해야 합니다.
📌 트랜잭션 프록시를 통해 같은 인스턴스 내의 다른 메서드를 호출할 때 유용
✔ 대안: 트랜잭션이 필요한 메서드를 별도의 Delegate Bean으로 분리
@Service
public class TransactionalTaskService {
@Transactional
public void performTransactionalTask() {
System.out.println("Performing transactional task.");
}
}
@Service
public class MyService {
@Autowired
private TransactionalTaskService transactionalTaskService; // 위임 빈 주입
public void performService() {
System.out.println("Main service logic execution started.");
// 위임 빈을 통해 트랜잭션 작업 실행
transactionalTaskService.performTransactionalTask();
System.out.println("Main service logic execution completed.");
}
}
📌 6️⃣ @Autowired
, @Inject
, @Value
, @Resource
와 BeanPostProcessor
🚨 Spring의 @Autowired
, @Inject
, @Value
, @Resource
는 BeanPostProcessor
를 통해 처리됩니다.
📌 이 때문에 BeanPostProcessor
나 BeanFactoryPostProcessor
내부에서는 사용할 수 없음
✅ 해결 방법
BeanPostProcessor
내부에서는 XML 설정이나@Bean
을 통해 명시적으로 빈을 등록해야 함- 예제:
@Configuration
public class AppConfig {
@Bean
public BeanPostProcessor myPostProcessor() {
return new MyBeanPostProcessor();
}
}
📌 7️⃣ Summary (요약)
✅ @Autowired
는 Spring이 제공하는 강력한 DI 기능
✅ JSR-330 @Inject
를 사용하면 Spring 종속성을 줄일 수 있음
✅ @Primary
, @Qualifier
로 주입될 빈 선택 가능
✅ @Autowired
, @Inject
, @Value
, @Resource
는 BeanPostProcessor
를 통해 처리됨 → BeanPostProcessor
내부에서는 사용할 수 없음 🚀
출처 : https://docs.spring.io/spring-framework/reference/core/beans/annotation-config/autowired.html
Using @Autowired :: Spring Framework
Only one constructor of any given bean class may declare @Autowired with the required attribute set to true, indicating the constructor to autowire when used as a Spring bean. As a consequence, if the required attribute is left at its default value true, o
docs.spring.io
'Spring Framework > Spring IoC' 카테고리의 다른 글
Dependency Injection (0) | 2024.06.11 |
---|---|
Bean Overview (0) | 2024.06.11 |
Dependencies and Configuration in Detail (0) | 2023.12.10 |
Fine-tuning Annotation-based Autowiring with @Primary or @Fallback (0) | 2023.07.08 |
Dependency Injection of Spring Framework (0) | 2023.05.01 |