스프링 빈과 의존관계
의존 관계란?
어떤 클래스가 다른 클래스를 통하여 수행될때 의존관계가 있다고 말한다.
ex) Controller가 MemberService를 통하여 회원 가입, 조회를 할 수 있다. 이러면 이 둘은 의존 관계가 있다.
의존 관계 설정
Controller 패키지 안에 MemberController java class를 생성하자.
@Controller
public class MemberController{
...
}
스프링이 실행될때 스프링 컨테이너가 만들어지고 어노테이션이 달린 객체들을 컨테이너 안에 생성해 스프링이 관리하게 된다. 이러면 스프링 빈이 관리 된다고 표현할 수 있다.
아래에 코드를 추가해주자.
private final MemberService memberservice;
@Autowired
public MemberController(MemberService memberservice){
this.memberservice = meeberservice;
}
생성자에 @Autowired 어노테이션이 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아 연결시켜준다. 다시말해 의존관계를 외부에서 넣어주는 것을 DI(Dedendency Injection), 의존성 주입이라고 한다.
실행시켜보면 에러가 뜰 것이다. 그 이유는 memberService가 스프링 빈으로 등록이 되어 있지않아 컨트롤러와 연결이 안되어있기 때문이다. MemberService에는 @Service, MemoryMemberRepository에는 @Repository 어노테이션을 위에 붙여주자.
@Service
public class MemberService {
...
}
@Repository
public class MemoryMemberRepository implements MemberRepository {
...
}
이렇게 controller, service, repository 어노테이션을 붙여놓으면 스프링이 실행될때 스프링 빈으로 등록이 된다. @Component 어노테이션이 붙어 있으면 스프링 빈으로 자동 등록이 되는데 앞에 3개 어노테이션은 @Component를 포함하는 어노테이션이기 때문에 등록이 된다. @Component를 스프링 빈으로 자동 등록되는걸 컴포넌트 스캔이다. HelloSpringApplication 코드를 보면 @SpringBootApplication 어노테이션을 볼 수 있다. 스프링이 이 파일이 들어있는 패키지, hello.hellospring 패키지 하위 디렉토리를 전부 스캔해서 자동으로 넣어주지면 동일 디렉토리거나 상위 디렉토리는 기본적으로 컴포넌트 스캔 대상이 안된다.
직접 스프링 빈 등록하기
@Service, @Repository, @Autowired 어노테이션을 모두 제거하고 진행
service 패키지 안에 SpringConfig java 클래스를 생성
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
스프링이 구동될때 @Configuration 어노테이션을 보고 @Bean 어노테이션을 찾아 스프링 컨테이너에 등록시켜 준다.
참고
- 필드 주입
- setter 주입
- 생성자 주입
의존 관계가 실행중에 동적으로 변하는 경우는 거의 없으르모 생성자 주입 을 권장한다.
실무에서는 controller, service, repository 같은 코드는 컴포넌트 스캔을 사용한다.
정형화 되지 않거나, 구현 클래스를 변경해야하면 Configuration을 통하여 등록한다.