728x90
참고 도서 : 스프링5 프로그래밍 입문 - 최범균 저 |
ch04. 의존 자동 주입
*3장은 명시적 의존 주입 (=설정 클래스에서 생성자 or set() 으로 의존 주입 코드 직접 작성) *4장은 자동 의존 주입 (=@Autowired) 사용 -> 스프링 컨테이너가 알아서 해당 타입 빈 객체 가져옴 |
[의존 자동 주입]
-스프링이 자동으로 의존하는 빈 객체를 주입해주는 기능 -설정 클래스에 의존 주입하지 않아도 스프링이 타입 일치하는 의존 빈객체 찾아서 주입 -의존 자동 주입 설정 : @Autowired or @Resource 사용 |
[@Autowired 이용 의존 자동 주입]
-의존 주입 대상에 @Autowired 붙이면 된다. -@Autowired를 필드나 set메소드에 붙이면 스프링은 타입이 일치하는 빈 객체 찾아 주입O -@Autowired + 필드 : 스프링이 해당 타입 빈 객체 찾아서 필드에 할당함 -@Autowired + set메소드 : 스프링은 메소드 파라미터 타입에 해당하는 빈 객체를 찾아서 인자로 주입함 -그 클래스에서 의존 빈 객체를 자동 주입했으면 해당 @Bean 설정 메소드 속에 명시적 작성했떤 의존 주입 코드는 삭제 |
//필드에 @Autowired
public class ChangePasswordService{
@Autowired
private MemberDao memberDao;
.....
}
----설정 클래스 속
@Configuration
public class AppCtx{
...
@Bean
public ChangePasswordService changePwdSvx() {
ChangePasswordService pwdSvc = new ChangePasswordService();
//pwdSvc.setMemberDao(memberDao());
return pwdSvc;
}
}
//set메소드에 @Autowired
public class MemberInfoPrinter{
...
@Autowired
public void setMemberDao(MemberDao memberDao) {
this.memDao = memberDao;
}
}
----설정 클래스 속
@Configuration
public class AppCtx{
...
@Bean
public MemberInfoPrinter infoPrinter() {
MemberInfoPrinter infoPrinter = new MemberInfoPrinter();
//infoPrinter.setMemberDao(memberDao());
return infoPrinter;
}
}
Q. 자동 의존 주입했는데, A. 타입 일치하는 빈 객체 없으면 -> Exception발생 B. 타입 일치하는 빈이 2개 이상이면 -> Exception발생 //스프링은 자동 주입 대상 타입 가진 빈을 정확하게 지정 X -> 자동주입 X |
[자동 주입 대상 빈 정확히 지정 방법]
▶ [ @Qualifier 애노테이션 사용 ] : 자동 주입 대상 빈 선택 가능
이 애노테이션은 기본적으로 두 위치에서 함께 사용해야 한다. ① @Bean 빈 설정 메소드에서 한정자 지정 ② @Autowired 사용한 위치에서 한정자 사용하여 자동 주입할 빈 선택 // 즉, 동일한 @Qualifier(“한정자”) 를 넣어서 주입할 빈 한정함. // @Qualifier도 필드, 메소드 모두에 적용 가능O |
-------------설정클래스 속-------------
@Configuration
public class 설정클래스 {
...
@Bean
@Qualifier("printer") //한정값 지정
public MemberPrinter memberPrinter1() {
return MemberPrinter();
}
public MemberPrinter memberPrinter1() {
return MemberPrinter();
}
}
----------------------------------------------
public MemberListPrinter{
...
@Autowired
@Qualifier("printer") //한정값을 사용하여 자동주입할 빈 객체 선택
public void setMemberPrinter(MemberPrinter printer) {
this.printer = printer;
}
}
//코드 해설 : setMemberPrinter() 메소드에 @Autowired 붙였으므로 해당 타입의 빈을 자동 주입하는데, 이때 @Qualifier로 한정자를 “printer”로 지정했으므로 -> 설정 클래스에 존재하는 동일 타입의 여러 빈 객체 중에서 @Qualifier 한정자를 “printer’로 지정한 빈이 선택되어 자동 의존 주입 된다. |
Q. 만약 빈 설정에 @Qualifier 한정자 지정 따로 없으면 ? |
▶ [ 이름으로 한정자 지정 ] : 자동 주입 대상 빈 선택 가능
-빈 설정에 @Qualifier 없으면 -> 빈 이름을 한정자로 지정함 -@Autowired 위치에 @Qualifier 없으면 -> 필드, 파라미터 이름을 한정자로 사용함 |
--- 설정 클래스 @Bean public MemberPrinter printer() { //빈 이름을 한정자로 지정 return new MemberPrinter(); } --- 해당 클래스 public class MemberInfoPrinter2{ ... @Autowired private MemberPrinter printer; //변수 이름을 한정자로 사용 } |
[상/하위 타입 관계와 자동 주입]
-예를 들어, (public class A extends B ) B를 상속받은 A가 있다고 생각해보자. -이 경우 A 클래스는 (하위), B 클래스는 (상위)가 된다. -두 타입 모두를 설정 클래스에서 빈 객체로 등록했다고 치자. -스프링 컨테이너는 B 타입 빈을 자동 주입하라는 @Autowired 태그 만나면, A 타입의 빈과 B 타입 빈 중에서 어떤 빈을 주입할지 알 수 없다. - 즉, B를 상속받은 A 타입 빈 마저 자동 주입 대상의 후보가 되는 것이다. -따라서, 상-하위 상속 관계에 있는 두 클래스 타입의 경계가 모호하므로 반드시 @Qaulifier 애노테이션을 붙여서 자동 주입 빈 한정짓자. |
[@Autowired 필수 여부 지정 방식] : 3 가지
: 자동 주입할 대상이 필수가 아닌데, 해당 빈이 존재하지 않는 경우, Exception 처리되지 않도록 지정 : 3 가지 방식은 메소드/필드 모두에 그대로 적용 O |
. ① @Autowired(required = false)
-@Autowired의 required 속성을 false로 지정하면 매칭되는 빈이 없어도 예외 발생하지 않으며, 스프링은 자동 주입을 수행 X -자동 주입할 빈이 존재하지 않으면 세터 메소드 호출 X |
. ② Optional<DateTimeFormatter> formatterOpt
-의존. 주입 대상 타입이 Optional인 경우, 일치하는 빈 존재하지 않으면 -> 값 없는 Optional 인자를 전달 -예외 발생X |
. ③ @Nullable
-의존 주입 대상의 파라미터에 붙이면, 자동주입이 존재하지 않을 때 -> null 인자 전달 -자동 주입할 빈이 존재하지 않아도 세터 메소드 호출 O |
//메소드 @Autowired(required = false) public void setDateFormatter(DateTimeFormatter dateTimeFormatter) { this.dateTimeFormatter = dateTimeFormatter; } @Autowired public void setDateFormatter(Optional<DateTimeFormatter> formatterOpt) { } @Autowired public void setDateFormatter(@Nullable DateTimeFormatter dateTimeFormatter) { this.dateTimeFormatter = dateTimeFormatter; } |
//필드 @Autowired(required = false) private DateTimeFormatter dateTimeFormatter; @Autowired private Optional<DateTimeFormatter> formatterOpt; @Autowired @Nullable private DateTimeFormatter dateTimeFormatter; |
[필수 여부 지정 방식 동작의 이해]
-자동 주입 대상 필드를 기본 생성자에서 초기화함
-근데, 자동 주입 대상 빈 객체가 없는 경우,
① @Autowired(required = false) //타입 일치하는 자동 주입 대상 존재X -> 필드, 메소드에 NULL 할당 X // -> 기본 생성자에서 초기화한 값을 출력함 //즉, 일치하는 빈 없으면 값 할당 자체를 하지 않음, ② @Nullable //타입 일치하는 자동 주입 대상 존재X -> NULL 할당 O ③Optional<DateTimeFormatter> formatterOpt //타입 일치하는 자동 주입 대상 존재X -> 값이 없는 Optional 할당 O |
[자동 주입과 명시적 의존 주입 간의 관계]
Q, 설정 클래스에서 의존 주입 코드 사용했는데, 자동 주입 기능 사용하면? A. @Autowired 자동 주입에 일치하는 빈을 우선적으로 주입함. |
//웬만하면, 일관되게 사용하는 것이 좋다. 대개 작동은 하지만, 문제 생기면 복잡
//의존 자동 주입 사용 권장함
---설정 클래스 ----------------------------
@Bean
@Qualifier("printer")
public MemberPrinter memberPrinter1() {
}
@Bean
public MemberPrinter memberPrinter2() {
}
@Bean
public MemberInfoPrinter infoPrinter() {
MemberInfoPrinter infoPrinter = new MemberInfoPrinter();
infoPrinter.setPrinter(memberPrinter2()); //의존 주입 코드
return infoPrinter;
}
-----------------------------------------
@Autowired
@Qualifier("printer") //자동 의존 주입 사용 우선
public void setPrinter(MemberPrinter printer) {
this.printer=printer;
}
728x90
'Web(웹)_관련 공부 모음 > [개념]_스프링 5 프로그래밍' 카테고리의 다른 글
ch06. 빈 라이프사이클과 범위 (0) | 2022.01.27 |
---|---|
ch05. 컴포넌트 스캔 (0) | 2022.01.26 |
ch03. 스프링 DI (0) | 2022.01.25 |
ch02. 스프링 시작 (0) | 2022.01.24 |
ch01. 스프링 기본 설명 (0) | 2022.01.24 |