"김영한 스프링 핵심 원리 기본편" 내용을 기반으로 작성한 내용입니다.
📝컴포넌트 스캔
@Configuration과 @Bean을 이용해도 되지만 점점 많아지게되면 힘들고 파일 하나에 엄청난 @Bean이 생겨날 수 있다.
이걸 깔끔하게 만드는 법이 컴포넌트 스캔이다. 컴포넌트 스캔은 @Component가 붙은 정보를 Bean으로 등록하게 된다.
컴포넌트 스캔
@Configuration
@ComponentScan(
excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Configuration.class))
public class AutoAppConfig {
}
컴포넌트
@Component
public class MemoryMemberRepository implements MemberRepository {}
이렇게 되면 @Component가 붙은 MemoryMemberRepository를 Bean으로 등록할 수 있다.
📝@Bean vs @Component
@Bean은 이제 더이상 쓸모 없는 행동일까? 어떤 상황에 @Bean을 쓰고 어떤 상황에 @Component를 쓰는지 알아보자
Bean 등록 방식 (@Bean, @Component)
// 이전 방식 사용
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService(); // MyService를 빈으로 등록
}
@Bean
public MyComponent myComponent() {
// MyComponent가 MyService를 필요로 한다고 명시적으로 주입
return new MyComponent(myService());
}
}
//이후 방식 사용
@Component
public class MyService {
// 빈으로 등록될 클래스
}
@Component
public class MyComponent {
private final MyService myService;
// @Autowired를 통해 Spring이 자동으로 MyService 빈을 주입함
@Autowired
public MyComponent(MyService myService) {
this.myService = myService;
}
}
비교하기 위해 동일한 빈 등록하는 방식을 Bean과 Component로 보여줬다.
- @Bean
- @Configuration이 필요하다
- 메소드 단위에 붙이게 된다. 해당 메소드는 클래스를 반환해야한다 (Component에서 해당 클래스가 @Component가 된다)
- 의존관계 주입을 직접 Inject을 하기 때문에 Autowired를 통해 Injection할 필요가 없다
- MyComponent에 myService()를 매개변수로 직접 넣어주고 있다.
- @Component
- 클래스 단위에 붙이게 된다. 해당 클래스는 빈으로 등록되게 된다.
- 의존관계 주입시 @Autowired를 사용한다
일반적으로 @Component를 많이 사용한다. @Bean 방식하고 비교하면 코드수도 확연히 줄어들게 된다. 하지만 @Bean도 필요할 때가 있다.
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource(); // 외부 라이브러리 클래스 인스턴스 생성
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("username");
dataSource.setPassword("password");
return dataSource;
}
}
HikariDataSource의 경우 외부 라이브러리이기 때문에 내가 직접 @Component를 붙일 수가 없다. 스프링에서 관리가 필요한데 이럴 경우 위 코드와 같이 직접 HikariDataSource의 객체를 만들고 return시킨 이후에 해당 것을 빈객체로 등록하게 되면 된다. 이럴 경우 HikariDataSource를 new해서 사용하면 안 되고 내가 Bean으로 등록한 DataSourceConfig의 dataSource()를 사용해야한다.