1. 설정 클래스에서 빈의 모습(직접 의존 주입했을 경우와 하지 않았을 경우)
설정 클래스에 빈으로만 등록해주고 의존 주입을 직접 set이나 생성자로 해주지 않아도 @Autowired를 통해 자동 의존 주입을 가능하게 할 수 있다. ※Component-scan 기능을 통해 설정 클래스에 빈으로 등록하지 않아도 원하는 클래스를 빈으로 등록할 수 있다.
@Configuration
public class AppCtx {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberRegisterService memberRegSvc() {
return new MemberRegisterService();
}
//자동 주입 기능을 사용하면 이렇게 의존을 주입하지 않아도 됨 set~~
@Bean
public ChangePasswordService changePwdSvc() {
ChangePasswordService pwdSvc = new ChangePasswordService();
pwdSvc.setMemberDao(memberDao());
return pwdSvc;
}
//이렇게 빈으로만 등록해놓고 @Autowired붙이면 된다.
@Bean
public ChangePasswordService changePwdSvc() {
return new ChangePasswordService();
}
2. @Autowired 애노테이션을 이용한 의존 자동 주입
@Autowired애노테이션은 필드에다 붙여도 되고 생성자, set메서드에 붙여도 된다.
아래 코드 블록은 set메서드에 @Autowired 붙인 경우이고
public class MemberInfoPrinter {
private MemberDao memDao;
private MemberPrinter printer;
public void printMemberInfo(String email) {
Member member = memDao.selectByEmail(email);
if (member == null) {
System.out.println("데이터 없음\n");
return;
}
printer.print(member);
System.out.println();
}
@Autowired
public void setMemberDao(MemberDao memberDao) {
this.memDao = memberDao;
}
@Autowired
@Qualifier("printer")
public void setPrinter(MemberPrinter printer) {
this.printer = printer;
}
}
아래 코드 블록은 필드에 @Autowired 붙인 경우이다.
public class ChangePasswordService {
@Autowired
private MemberDao memberDao;
public void changePassword(String email, String oldPwd, String newPwd) {
Member member = memberDao.selectByEmail(email);
if (member == null)
throw new MemberNotFoundException();
member.changePassword(oldPwd, newPwd);
memberDao.update(member);
}
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
}
아래 코드 블록은 생성자를 통해 자동 의존 주입을 위해 필드에 @Autowired를 붙이고 기본 생성자와 MemberDao를 인자로 가지는 생성자를 추가해준 모습이다. 기본 생성자를 생성해준 이유는 AppCtx클래스에서 기본 생성자를 통해 객체를 생성하기 위함이다.
public class MemberRegisterService {
@Autowired
private MemberDao memberDao;
public MemberRegisterService() {
}
public MemberRegisterService(MemberDao memberDao) {
this.memberDao = memberDao;
}
public Long regist(RegisterRequest req) {
Member member = memberDao.selectByEmail(req.getEmail());
if (member != null) {
throw new DuplicateMemberException("dup email " + req.getEmail());
}
Member newMember = new Member(
req.getEmail(), req.getPassword(), req.getName(),
LocalDateTime.now());
memberDao.insert(newMember);
return newMember.getId();
}
}
※@Autowired가 생략 가능한 경우(스프링 4.3부터 가능)
public class MemberRegisterService {
private MemberDao memberDao;
public MemberRegisterService(MemberDao memberDao) {
this.memberDao = memberDao;
}
public Long regist(RegisterRequest req) {
Member member = memberDao.selectByEmail(req.getEmail());
if (member != null) {
throw new DuplicateMemberException("dup email " + req.getEmail());
}
Member newMember = new Member(
req.getEmail(), req.getPassword(), req.getName(),
LocalDateTime.now());
memberDao.insert(newMember);
return newMember.getId();
}
}
MemberDao가 빈으로 등록되어 있고 MemberRegisterService(MemberDao memberDao)같이 생성자가 하나 있을 경우 위와 같이 @Autowired 생략되어 있어도 의존 자동 주입 가능하다. ** 그러나 상호 참조 관계에서 이렇게 생성자로 만들면 문제가 발생할 수 있다.(교착상태에 빠짐)
또한, 아래와 같이 생성자를 없애도 의존 자동 주입이 가능하다.
public class MemberRegisterService {
@Autowired
private MemberDao memberDao;
public Long regist(RegisterRequest req) {
Member member = memberDao.selectByEmail(req.getEmail());
if (member != null) {
throw new DuplicateMemberException("dup email " + req.getEmail());
}
Member newMember = new Member(
req.getEmail(), req.getPassword(), req.getName(),
LocalDateTime.now());
memberDao.insert(newMember);
return newMember.getId();
}
}
3. @Autowired(required=false), Optional, @Nullable의 관계
4. 자동 주입과 명시적 의존 주입(수동)이 동시에 설정되어있다면?
설정 클래스에서 세터 메서드를 통해 의존을 주입해도 해당 세터 메서드에 @Autowired애노테이션이 붙어 있으면 자동 주입을 통해 일치하는 빈을 주입한다.
**자동 주입을 하는 코드와 수동으로 주입하는 코드가 섞여 있으면 주입을 제대로 하지 않아 NullPointerException이 발생할 때 원인을 찾기 힘들 수 있으니 의존 자동 주입을 사용하고 있으면 일부 자동 주입을 적용하기 어려운 경우를 제외하고는 일관적으로 의존 자동 주입을 사용하는 것이 좋다.
'Back-end > Spring-핵심& webMVC' 카테고리의 다른 글
MessageSource 메시지 국제화 처리 (0) | 2021.06.05 |
---|---|
QueryString, request.getParameter, request.getParameterValues (0) | 2021.06.03 |
@ModelAttribute의 쓰임과 Model, ModelMap, ModelAndView (0) | 2021.05.11 |
ch5. 컴포넌트 스캔(#스프링5 프로그래밍 입문-최범균 저) (0) | 2021.05.07 |
JSP 태그 라이브러리 (0) | 2021.05.05 |