728x90
의존이란?
- DI (Dependency Injection), 의존 주입이라고 함
- 객체 간의 의존을 의미
import java.time.LocalDateTime;
public class MemberRegisterService{
private MemberDao memberDao = new MemberDao();
public void regist(RegisterRequest req){
// 이메일로 회원 데이터(Member) 조회
Member member = memberDao.selectByEmail(req.getEmail());
if(member != null){
// 같은 이메일을 가진 회원이 이미 존재하면 익셉션 발생
throw new DuplicateMemberException("dup email" + req.getEmail());
}
// 같은 이메일을 가진 회원이 존재하지 않으면 DB에 삽입
Member newMember = new Member(req.getEmail(), req.getPassword(), req.getName(),
LocalDateTime.now());
memberDao.insert(newMember);
}
}
- MemberRegisterService 클래스가 DB 처리를 위해 MemberDao 클래스의 메서드를 사용한다
- 한 클래스가 다른 클래스의 메서드를 실행할 때 이를 ‘의존’한다고 표현
💡 의존은 변경에 의해 영향을 받는 관계를 의미한다. MemberDao의 insert 메서드의 이름을 변경하면 이 메서드를 사용하는 클래스의 소스코드도 함께 변경된다. 이렇게 변경에 따른 영향이 전파되는 관계를 ‘의존’한다고 표현한다.
- 의존하는 대상이 있으면 그 대상을 구하는 방법이 필요
- 가장 쉬운 방법은 의존 대상 객체를 직접 생성하는 것
- MemberRegisterService 객체를 생성하는 순간에 MemberDao 객체도 함께 생성됨
- 쉽긴 하지만 유지보수 관점에서 무제가 있음
- DI와 서비스 로케이터로 의존 객체를 구할 수 있음
- 가장 쉬운 방법은 의존 대상 객체를 직접 생성하는 것
DI를 통한 의존 처리
- 의존하는 객체를 직접 생성하는 대신 의존 객체를 전달받는 방식 사용
import java.time.LocalDateTime;
public class MemberRegisterService{
private MemberDao memberDao;
public MemberRegisterService(MemberDao memberDao){
this.memberDao = memberDao;
}
public void 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);
}
}
- 생성자를 통해서 의존 객체를 전달 받음. 즉 의존하고 있는 객체를 주입(Injection) 받은 것
- MemberRegisterService 클래스를 사용하는 코드는 객체를 생성할 때 생성자에 MemberDao 객체를 전달해야 함
MemberDao dao = new MemberDao();
// 의존 객체를 생성자를 통해 주입
MemberRegisterService svc = new MemberRegisterService(dao);
DI와 의존 객체 변경의 유연함
- 회원의 암호 변경 기능을 제공하는 ChangePasswordService 클래스도 의존 객체를 직접 생성한다고 가정
public class ChangePasswordService{
private MemberDao memberDao = new MemberDao();
}
- 회원 데이터의 빠른 조회를 위해 캐시를 적용해야하는 상황이 발생해 MemberDao 클래스를 상속받은 CachedMemberDao 클래스 생성
public class CachedMemberDao extends MemberDao{
}
- 캐시 기능을 적용한 CachedMemberDao를 사용하려면 MemberDao 객체가 필요한 클래스의 소스를 모두 변경해야 함
- 동일한 상황에서 DI를 사용하면 수정할 코드가 줄어듦
@Configuration : 스프링 설정 클래스
@Bean : 해당 메서드가 생성한 객체를 스프링 빈이라고 설정. 메서드마다 한 개의 빈 객체 생성
@Bean 설정과 싱글톤
- 스프링 컨테이너가 생성한 빈은 싱글톤 객체
- @Bean 이 붙은 메서드에 대해 한 개의 객체만 생성 (몇 번을 호출하더라도 항상 같은 객체 리턴)
- 스프링은 설정 클래스를 그대로 사용하지 않고, 설정 클래스를 상속한 새로운 설정 클래스를 만들어 사용
두 개 이상의 설정 파일 사용
- 설정하는 빈의 개수가 증가하면 한 개의 클래스 파일에 설정하는 것보다 영역별로 설정 파일을 나누면 관리하기가 편해짐
- AnnotationConfigApplicationContext 의 생성자의 인자는 가변 인자이기 때문에 목록을 콤마로 구분해서 전달 가능
@Configuration , @Autowired
- @Autowired 는 스프링의 자동 주입 기능을 위한 것. 해당 타입의 빈을 찾아서 필드에 할당.
- 스프링 빈에 의존하는 다른 빈을 자동으로 주입하고 싶을 때 사용
- 스프링 컨테이너는 @Configuration 어노테이션을 붙인 설정 클래스를 스프링 빈으로 등록
@Import
- 함께 사용할 설정 클래스를 지정
- @Import를 사용해서 포함한 설정 클래스가 다시 @Import를 사용할 수 있음
- 설정 클래스를 변경해도 AnnotationConfigApplicationContext를 생성하는 코드는 최상위 설정 클래스 한 개만 사용하면 됨
'스프링' 카테고리의 다른 글
스프링5 프로그래밍 입문 - AOP 프로그래밍 (0) | 2023.10.28 |
---|---|
스프링5 프로그래밍 입문 - 빈 라이프사이클과 범위 (0) | 2023.10.02 |
스프링5 프로그래밍 입문 - 컴포넌트 스캔 (0) | 2023.10.02 |
스프링5 프로그래밍 입문 - 의존 자동 주입 (0) | 2023.10.02 |
스프링5 프로그래밍 입문 - 스프링 프로젝트 시작하기 (0) | 2023.10.02 |