의존성 주입(DI)을 간단히 말하면, 클래스에서 필요로 하는 의존성을 직접 생성하지 않고, 외부에서 주입받는 방식이다.
이를 통해 클래스 간의 결합도를 낮추어 유연성을 높일 수 있다.
예를들어, A클래스가 B클래스를 의존한다면, A클래스에서 B클래스의 객체를 생성하고 사용하는것이 아니라, 외부에서 B클래스의 객체를 생성하여 주입하는 방식을 사용하는 것이다.
public class UserService {
private final UserRepository userRepository = new UserRepositoryImpl();
public void addUser(User user) {
userRepository.save(user);
}
}
예를들어, UserService클래스는 UserRepository클래스에 의존하고 있는데,
UserService클래스 내에서 UserRepository객체를 생성하여 사용하고 있다.
이를 DI를 적용한다면
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void addUser(User user) {
userRepository.save(user);
}
}
(생성자를 이용한 DI)
UserService클래스의 생성자에서 UserRepository객체를 주입받도록 하였다.
이제 UserService객체를 생성할 때, UserRepository객체를 주입하면 된다.
(필드주입)
@Autowired private MemberService memberService;
필드주입은 위의 생성자를 이용한 DI예시에서 생성자 대신 필드에 바로 작성한 것임
(필드주입은 권장하지 않음)
@Autowired
public void setMemberService(MemberService memberService){
this.memberService = memberService;
}
setter 주입은 위와 같다
setter가 public으로 되어있기 때문에, 언제나 setter에 접근가능하다.. 는 것이 문제!
생성자 주입을 권장한다.
@Autowired 어노테이션은 객체를 자동으로 주입해주는 기능을 한다.
스프링 컨테이너가 해당 클래스 타입의 빈을 찾아서 자동으로 주입해준다.
이를 사용하면, 클래스 내부에서 객체 생성 코드를 작성하지 않고, 스프링 컨테이너에서 주입받아 사용할 수 있다.
@Autowired 어노테이션을 사용하기 위해서는, 해당 클래스가 스프링 빈으로 등록되어야 하는데
빈을 등록하는 방법은 크게 2가지가 있다.
1. ComponentScan 과 자동 의존관계 설정
@Component 어노테이션이 있으면 스프링 빈으로 자동 등록되는데,
@Controller, @Service, @Repository 들도 @Component를 포함하기 때문에 스프링 빈으로 등록된다.
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired//멤버컨트롤러가 생성될 때 스프링 빈에 등록되어있는 멤버 서비스 객체를 가져다 넣어줌.
public MemberController(MemberService memberService){
this.memberService = memberService;
}
}
위 코드는:
MemberController의 생성자에 @Autowired 어노테이션을 사용하여, 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입하도록 한다.
(참고: 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본적으로는 유일한 하나의 객체만 등록해서 공유한다. 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. )
스프링 빈을 등록하는 2번째 방법:
자바 코드로 직접 스프링 빈 등록하기.
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
}
@Bean 어노테이션을 사용하면 개발자가 직접 빈을 등록할 수 있다.
해당 어노테이션을 붙인 메소드의 반환값이 빈으로 등록된다.
.
.
실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리같은 코드는 컴포넌트 스캔방식을 사용하고,
정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.
'웹개발 > SpringBoot' 카테고리의 다른 글
[JPA] 엔티티 수정시 Dirty checking(변경 감지), Merge(병합) (0) | 2023.05.07 |
---|---|
JPA, Spring Data JPA (0) | 2023.03.21 |
빌드하고 실행하기 (0) | 2023.03.18 |
ObjectMapper (0) | 2023.03.14 |
AOP(Aspect Oriented Programming) (1) | 2023.03.14 |
댓글