public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(DependencyConfig.class); // (1)
MyService myService = ctx.getBean(MyService.class);// (2)
myService.doStuff();
}
ApplicationContext ctx = new AnnotationConfigApplicationContext(DependencyConfig.class);
설정 클래스(Config Class)
라고 한다.설정 클래스
는 해당 애너테이션이 달린 클래스이다.@Configuration
@Component
Config 클래스
로 설정해줌 = 스프링 설정 정보로 만든다.
@Configuration 클래스 자체가 BeanDefinition에 등록됨
클래스 내에 선언된 모든 @Bean 메서드도 BeanDefinition에 등록됨
외부 라이브러리 또는 내장 클래스를 Bean으로 등록하고자 할 경우에 사용(개발자가 직접 제어가 불가능한 클래스)
이전까지는 Bean을 등록할 때, @Bean
을 통해서 설정 정보에 등록할 Bean들을 직접 작성했다. 하지만 하나씩 작성해서 등록하게 되면, 정보가 누락되는 등 문제가 발생할 수 있다.
@ComponentScan을 Config 클래스에 붙여주면, @Component가 붙은 모든 클래스를 Bean으로 등록해주기 때문에 편리하다.
@Component
@Controller
& @RestController
@Service
: 비즈니스 로직에서 사용@Repository
: 스프링 데이터 접근 계층에서 사용@Configuration
: 스프링 설정 정보에서 사용
@ComponentScan
을 사용할 때,@Configuration
이 붙은 클래스도 자동으로 빈으로 등록된다.
@Configuration
내부에 @Component
애너테이션이 있기 때문에
@ComponentScan + @Component
와 @Configuration + @Bean
을 혼용해서 사용하지 말자!
기존에 작성한 설정 파일에 @Configuration
가 붙어있다면, 충돌이 일어나 문제가 발생할 수 있다.
@Configuration
애너테이션을 제거하거나 아래 코드를 추가해주자.
@ComponentScan(excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Configuration.class))
@ComponentScan + @Component
만 사용했을 때에 설정 정보(Config 클래스)에 어떤 의존 객체를 주입할지 명시해주지 않기 때문에 의존 주입이 필요한 생성자 부분에 @Autowired
를 통해 의존 관계 주입이 필요합니다.
의존성 주입 시에, 설정 정보를 정의하는 대신 의존관계 자동 주입을 해준다.
@Component
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
위와 같이, 의존성 주입이 필요한 경우에 XML 파일이나 설정 정보(Config 클래스)를 정의한다.
@Configuration
public class Config {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemberRepository();
}
}
하지만, @Autowired
를 사용하면 굳이 설정 정보를 작성하지 않아도 자동으로 의존성 주입을 실행해준다.
@Component
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
스프링에서 Bean 인스턴스가 생성된 이후 @Autowired를 설정한 메서드가 자동으로 호출되고, 인스턴스가 자동으로 주입된다.
Bean이 하나의 생성자만을 가질 경우에, @Autowired
는 자동으로 삽입되기 때문에 작성하지 않아도 된다.
탐색할 패키지의 시작 위치를 지정하고, 해당 패키지부터 하위 패키지 모두 탐색한다.
@ComponentScan()의 매개변수로 basePackages = “시작 위치”
를 작성한다.
지정하지 않으면, @ComponentScan이 붙은 설정 정보 클래스의 패키지가 시작 위치가 된다.
스프링 부트를 사용한다면, @SpringBootApplication
을 프로젝트 시작 루트 위치에 두자!
@Component
+ @ComponentScan
과 @Configuration
+ @Bean
으로 나누어서 사용할 수 있다.
Q) 왜 굳이 나누었을까?
A) @Bean과 @Component의 용도가 다르기 때문에!
@Bean
은 메서드 영역에 올라가는 애노테이션으로, 해당 메서드에서 반환되는 리턴값을 Bean으로 등록한다.
@Component
는 클래스에 붙이는 애노테이션으로, 이 클래스에 Bean이 담겨져 있다는 것을 알려준다. 런타임 시에, 스프링이 ComponentScan을 해서 자동으로 Bean을 찾고 등록한다.
→ 빈은 메소드 레벨에서, 컴포넌트는 클래스 레벨에서 사용됨
@Component
+ @ComponentScan
- 개발자가 직접 작성한 클래스를 Bean 등록하고자 할 경우 사용
@Configuration
+ @Bean
- 개발자가 컨트롤이 불가능한 외부 라이브러리 또는 내장 클래스를 Bean으로 등록하고자 할 경우 사용
[참고]
https://lasbe.tistory.com/111
https://hyune-c.tistory.com/entry/Component-vs-Configuration
https://yhmane.tistory.com/129