@Configuration과 @Bean
2편에서 했던 컴포넌트 스캔의 경우
라는 과정을 거쳤는데, @Bean은 다른 메커니즘을 갖는다.
2편에서 했던 @Component방식은 클래스 자체를 bean으로 만드는 반면 @Bean은 메서드가 만들어주는 객체를 bean으로 만드는 것이다. 즉, 개발자가 작성한 메서드가 빈 생성의 주체가 된다.
빈의 생성을 개발자가 직접 제어한다는 것이다.
따라서 구현은 다음과 같이 해야한다.
/**
* bean 설계도
* @Component: 생성자 기반
* @Bean: 메서드 기반
*/
@Getter
public class BeanDefinition {
private final Class<?> beanClass;
// @Bean용
private final Object factoryInstance; //@configuration 달린 클래스
private final Method factoryMethod; //그 안에@Bean달린 메서드
public BeanDefinition(Class<?> beanClass) {
this(beanClass, null, null);
}
// @Bean용
public BeanDefinition(Class<?> beanClass, Object factoryInstance, Method factoryMethod) {
this.beanClass = beanClass;
this.factoryInstance = factoryInstance;
this.factoryMethod = factoryMethod;
}
public boolean isFactoryMethod() {
return factoryMethod != null;
}
}
구현과정에서 약간의 문제가 있었다. 현재 구현과정에서는 의존성을 이름 기준으로 해결했는데, 그렇게 하면 다음과 같은 코드를 만났을 때 문제가 생긴다.
@Configuration
public class TestJacksonConfig {
@Bean
public JavaTimeModule testBaseJavaTimeModule() {
return new JavaTimeModule();
}
@Bean
public ObjectMapper testBaseObjectMapper(JavaTimeModule testBaseJavaTimeModule) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(testBaseJavaTimeModule);
return objectMapper;
}
}
메서드 이름을 기준으로 했을 경우 위의 코드에서
처음에는 순서가 문제인 줄 알았는데 testBaseJavaTimeModule에서 testBaseObjectMapper 순으로 돈다고 해도, bean을 javaTimeModule으로 찾기 때문에 못 찾는건 똑같다.
따라서 의존성 해결을 이름 기준에서 타입 기준으로 바꿔야 한다.