DI
는 Dependency Injection
의 약자로 우리말로는 의존주입
이라 번역의존
이란 객체간의 의존을 의미의존
한다고 표현(변경에 의해 영향을 받는 관계)DIP
와는 비슷한 개념IoC(Inversion of Control)
제어 반전의 한 종류
용어가 정확하게 구분되어 있지는 않지만, 대략 IoC > DIP > DI 정도로 정리가능
자세한 사항은 링크 참조: https://bit.ly/2Zt9cnf
SOLID
- 단일 책임 원칙(Single responsibility principle) - SRP
- 개방 폐쇄 원칙(Open/closed principle) - OCP
- 리스코프 치환 원칙(Liskov substitution principle) - LSP
- 인터페이스 분리 원칙(Interface segregation principle) - ISP
- 의존관계 역전 원칙(Dependency inversion principle) -
DIP
의존 객체를 전달받는 방식
을 이용
// MemberRegisterService.java
public class MemberRegisterService {
private MemberDao memberDao;
// MemberDao 객체를 전달 받아 DI를 구현
public MemberRegisterService(MemberDao memberDao) {
this.memberDao = memberDao;
}
...
}
변경의 유연함
유연함
을 가져갈 수 있음(주입 대상이 되는 객체를 생성하는 코드만 변경하면 됨)// MemberRegisterService.java
public class MemberRegisterService {
private MemberDao memberDao;
// 생성자를 통해 의존 객체를 주입 받음
public MemberRegisterService(MemberDao memberDao) {
this.memberDao = memberDao;
}
public Long regist(RegisterRequest req) {
// 주입 받은 의존 객체의 매서드를 사용
Member member = memberDao.selectByEmail(req.getEmail());
...
memberDao.insert(newMember);
return newMember.getId();
}
}
생성자
를 통해 의존 객체를 주입받아 필드에 할당두 개 이상이어도 동일한 방식
으로 주입// MemberInfoPrinter.java
public class MemberInfoPrinter {
private MemberDao memDao;
private MemberPrinter printer;
...
// setter를 통해 의존 객체를 주입 받는다.
public void setMemberDao(MemberDao memberDao) {
this.memDao = memberDao;
}
public void setPrinter(MemberPrinter printer) {
this.printer = printer;
}
}
setter 매서드
를 이용하여 객체를 주입생성자 방식
장점: Bean 객체를 생성하는 시점에 모든 의존 객체가 주입
, 그러나 생성자의 파라미터가 많을 경우 일일히 확인
해 주어야 함setter 매서드 방식
: sstter 매서드 이름을 통해 어떤 의존 객체가 주입 되는지 알 수 있음
, 그러나 정확한 전달이 안될 시 NullPointerException
발생가능// AppCtx.java
@Configuration
public class AppCtx {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberRegisterService memberRegSvc() {
// memberDao() 매서드 호출
return new MemberRegisterService(memberDao());
}
@Bean
public ChangePasswordService changePwdSvc() {
ChangePasswordService pwdSvc = new ChangePasswordService();
// memberDao() 매서드 호출
pwdSvc.setMemberDao(memberDao());
return pwdSvc;
}
...
}
memberRegSvc() 매서드와 changePwdSvc() 매서드는
둘 다 memberDao() 매서드를 실행
그리고 memberDao() 매서드는매번 새로운 MemberDao 객체를 생성해서 리턴
두 매서드는 과연같은
MemberDao 객체를 사용하는가?
한 개의 객체만 생성
항상 같은
객체를 리턴새로운 설정 클래스
를 만들어서 사용하기 때문동일한 객체를 리턴
// 이해를 돕기 위한 가상의 코드. 실제 코드는 이보다 훨씬 복잡하다.
public class AppCtxExt extends AppCtx {
private Map<String, Object> beans = ...;
@Override
public MemberDao memberDao() {
if(!beans.containersKey("memberDao"))
beans.put("memberDao", super.memberDao());
return (MemberDao) beans.get("memberDao");
}
...
}
동일 객체
를 리턴@AutoWired
어노테이션을 통해 필요한 Bean 객체를 자동 주입@Import
어노테이션을 통해 함께 사용할 클래스를 지정