@Bean을 왜 쓰냐? 마치 datapool 처럼 객체를 계속 만들어서 memory에 과부하가 가지 않도록 하고 미리 spring container에 등록한 객체를 빌려서 사용하도록 유도하여 메모리 소모량을 줄일 수 있기 때문이다.
생성자에 @Autowired
가 있으면 스프링이 관련된 객체를 스프이 Container에서 찾아서 넣어준다.
이렇게 객체 의존 관계를 외부에서 넣어주는 것. 이를
DI(dependency injection)
라고 한다.
Spring은 Spring Container에 @Bean을 등록할 때 기본적으로 싱글톤(하나만 등록해서 공유)으로 등록한다.
따라서 같은 @Bean이면 모두 같은 instance이다.
설정으로 싱글톤이 아니게 설정할 수 있지만 특별한 경우아니고선 대부분 싱클톤으로 등록한다.
memberRepository
가 필요하네?! 하고 딱 저부분을 가져와서 넣어준다. 이것이 바로 의존관계 주입 즉 DI 되시겠다.@Component
요게 있으면 스프링 빈으로 자동 등록을 해준다.@Component
하위에 있는 것이 @Controller
,@Service
,@Repository
가 있고@Controller
가 스프링 빈으로 자동 등록된 이유도 Component Scan이 가능하기 때문이다.생성자에
@Autowired
를 사용하면 객체 생성 시점에 Spring Container에서 해당 Bean을 찾아서 주입하는데 이때 싱성자가 1개밖에 없다면 생략가능!
그렇다면 어디어디를 spring project가 뒤지는가? 바로 얘 ProjectNameApplication
이 파일이 있는 package
내에 있는 모든 파일 되시겠다.
하지만 억지로 외부 클래스도 컴포넌트로 등록하겠다고 한다면 @componentscan
이라는 어노테이션을 추가하면 되긴 한다.
@Configuration
public class SpringConfig {
// spring container에 등록하고 싶은 class를 생성자 함수로 작성
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
}
이렇게 SpringConfig 라는 클래스 파일을 하나 만들고 그 안에 @Bean
annotation을 사용하여 클래스들
을 등록해도 좋다.
이때 가능한 @Component
들은 @Service
, @Repository
가 있고 @Controller
는 이런식으로 spring config로는 등록이 불가하다.
생성자 주입
을 권장한다. 만약 수정 소요가 있다면 config 파일을 손보고 다시 올린다.문제는 public으로 들어가기 때문에 controller단에서 아무 개발자가 건들 수 있다.
이는 앞서 언급했던 문제가 생길 수 있기 때문에 지양하는 것이 좋다.
이렇게 되면 원래는 loading할 때 조립시점(spring prj가 최초 로딩되는 시점)에서 바꾸는건데 이 이후에 바뀔 가능성이 있기 때문에 사용을 지양하자.
실무에서는 주로 정형화된 Controller, Service, Repository와 같은 코드는 Component Scan을 사용한다.
그리고 정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 springconfig를 통해 @Bean으로 등록한다.
참고로 위처럼 하려면 당연히 뒤따라야하는 것이 요구사항을 사전이 미리 정확하게 정의하여 Component Scan할 class와 springconfig로 등록할 class를 명확하게 구분지어야한다.
즉 자바로 수동으로 등록해주면 코드가 거의 연체동물마냥 유연해지고 유지보수 소요가 대폭 줄어든다.