의존성 자동 주입
말 그대로 의존성을 자동으로 주입하는 방식
의존성 자동 주입을 위해서는
@Autowired
@Resource
등의 어노테이션 사용
책에서는 @Autowired에 대한 설명만 진행
@Autowired
💡 @Autowired: 자동 주입 기능, 스프링이 알아서 의존 객체를 찾아 주입한다. 의존을 주입할 대상에 애노테이션을 붙이기만 하면 된다.
- @Autowired 애노테이션을 붙이면 설정 클래스에서 의존을 주입하지 않아도 된다.
- 스프링이 해당 타입의 빈 객체를 찾아서 필드에 할당
간단하게 말해서
pulbic class TestClass {
@Autowired
private TestObject testObject;
...
}
스프링 컨텍스트에 등록된 TestObject 의 빈 객체를 가져와 사용하겠다는 의미
이렇게 하면
public class AppCtx {
...
@Bean
public TestObject testObjet() {
return new TestObject();
}
// 아래 부분 필요 X
@Bean
public TestClass testClass {
TestClass testClass = new TestClass();
testClass.setTestObject(testObject);
return testClass;
}
}
@Configuration
클래스에서 의존성 주입하는 클래스를 따로 명시하지 않아도 됨
일치하는 빈이 없는경우
@Autowired 어노테이션을 적용한 대상에 일치하는 빈이 없으면
UnsatisfiedDependencyException : Error creating bean.. 어찌구
Exception 발생
@Qualifier 어노테이션을 이용한 의존 객체 선택
단순하게 설명하자면
같은 클래스의 빈을 두개 이상 만들어서 사용하고 싶다!!
할때 @Qualifier 어노테이션으로 빈 이름을 설정해서 필요할 때 원하는 이름의 빈을 꺼내 사용하는 방법
빈 등록 할 때 @Qualifier 따로 명시하지 않으면 빈의 이름을 한정자로 지정
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService = ac.getBean("memberService", MemberService.class);
스프링 컨텍스에서 getBean() 메서드로 빈 조회해서 이름 확인 가능
상위/하위 타입 관계와 자동 주입
상속관계를 가지는 빈 객체를 @Autowired 로 자동 주입할 때 충돌 발생 가능
스프링은 @Autowired로 빈 주입 시, 타입 기준으로 빈을 서치
@Autowired
public void setMemberPrinter(MemberPrinter printer) { ... }
이 경우 MemberPrinter 타입을 찾게 되는데
AppCtx 설정에
@Bean
public MemberPrinter memberPrinter1() { return new MemberPrinter(); }
@Bean
public MemberSummaryPrinter memberPrinter2() { return new MemberSummaryPrinter(); }
이처럼
MemberPrinter, MemberPrinter의 하위 클래스를 각각 반환하는 빈이 등록되있음
즉, MemberPrinter 타입 빈이 두개 존재
@Qualifier 어노테이션으로 한정자 지정해서 해결 가능
@Autowired 어노테이션 필수 여부
@Autowired는 기본적으로 @Autowired 어노테이션을 붙인 타입에 해당하는 빈이 존재하지 않으면 Exception 발생
required 속성을 false로 설정해서 매칭되는 빈이 없으면 자동주입을 하지 않는 방법 가능
@Autowired(required = false)
private Optional<MemberPrinter> printer;
이렇게 사용하게 되면 빈이 없을 경우, null 주입하거나 아무 동작도 하지 않음
** Optional 과 함께 사용해서 null 에 대해 처리해주는 코드 함께 작성 권장 **
2025.06.25 - [끄적/BE] - Optional
@Nullable
문자 그대로 null 가능하다고 명시적으로 표시하는 용도
목적 | 해당 변수/파라미터/리턴값이 null일 수 있음을 명시 |
주요 위치 | 필드, 메서드 파라미터, 메서드 반환값 |
1. 의존성 주입에서
@Component
public class MemberInfoPrinter {
private MemberPrinter printer;
@Autowired
public void setPrinter(@Nullable MemberPrinter printer) {
this.printer = printer;
}
}
- MemberPrinter 빈이 없어도 예외 없이 null이 주입됨
- @Autowired(required = false)와 유사 기능
2. 일반 메서드 파라메터
public String getNickname(@Nullable String username) {
return (username != null) ? username : "Guest";
}
3. return 값
@Nullable
public Member findByEmail(String email) {
...
return null; // 없을 수도 있음
}
자동 주입과 명시적 의존 주입 간의 관계
@Configuration 클래스에서 의존성 주입했는데, 자동 주입 대상이면??
명시적 주입
@Bean
public MemberInfoPrinter infoPrinter() {
MemberInfoPrinter infoPrinter = new MemberInfoPrinter();
infoPrinter.setPrinter(memberPrinter2()); // 명시적 주입: SummaryPrinter
return infoPrinter;
}
자동 주입
@Autowired
@Qualifier("printer")
public void setPrinter(MemberPrinter printer) {
this.printer = printer;
}
출력 결과는 **memberPrinter1() (일반 MemberPrinter)**를 사용한 것으로 확인됨.
즉, 명시적으로 주입한 memberPrinter2()가 무시되고, @Autowired에 의해 memberPrinter1()이 주입됨
자동 주입이 명시적 주입을 덮어쓰기 때문
Spring에서는 @Bean 메서드로 생성한 객체에 대해 내부적으로 생성 이후 @Autowired를 기반으로 DI 작업을 수행
- @Bean 메서드(infoPrinter())가 실행되어 객체 생성 및 명시적 주입 수행
- Spring 컨테이너는 해당 객체에 @Autowired가 선언된 세터가 있으면 자동 주입 수행
>> 이 과정에서 이미 명시적으로 주입된 필드라도 다시 덮어씀
즉, 자동 주입이 명시적 Setter 호출보다 나중에 실행, 자동 주입이 반영됨
'복습 > Spring' 카테고리의 다른 글
[Spring 5 프로그래밍 입문] 스프링 DI (0) | 2025.06.22 |
---|