원래 내가 알던 @Component와 @Bean의 차이는 매우 단순했다.
이 두 설명 안에서 간극이 존재했다.
@Component : 내가한거 @Bean : 내가 안한거 라면...
내가 @Configuration 클래스에 넣어둔 @Bean 어노테이션은 뭐지? 왜 관리되는거고 왜 작동하는거지? 라는 의문에 다시 찾아보게 되었다.
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
위와 같이 RedisConnectionFactory를 리턴해서 하나의 빈으로 명시하면
@Service
public class RedisService {
private final RedisConnectionFactory redisConnectionFactory;
public RedisService(RedisConnectionFactory redisConnectionFactory) {
this.redisConnectionFactory = redisConnectionFactory;
}
// ...
}
위와 같이 주입됐을 시 Lettuce가 선택된다.
-> Component는 내가 선언한 클래스에 달아 줄 수 있는 어노테이션이다. 그러나 외부 라이브러리 등 내가 @Component 어노테이션을 달아 줄 수 없는 곳이라면 @Configuration 선언한 클래스 안에서 @Bean 어노테이션을 붙은 매서드를 만들고, 이 매서드가 반환하는 값을 스프링 Bean으로 설정 해서 사용 가능하다(Application Context)
@Component Preferable for component scanning and automatic wiring.
When should you use @Bean?
Sometimes automatic configuration is not an option. When? Let's imagine that you want to wire components from 3rd-party libraries (you don't have the source code so you can't annotate its classes with @Component), so automatic configuration is not possible.
The @Bean annotation returns an object that spring should register as bean in application context. The body of the method bears the logic responsible for creating the instance.
@Component는 컴포넌트 스캔 및 자동 와이어링에 적합합니다.
@Bean은 언제 사용해야 할까요?
Autowiring이 불가능한 경우가 있습니다. 예를 들어, @Component 주석을 클래스에 추가할 수 없는 서드파티 라이브러리의 컴포넌트를 와이어링하려는 경우입니다. 이 경우 @Bean을 사용하여 객체를 생성하고 Spring 애플리케이션 컨텍스트에 빈으로 등록할 수 있습니다. @Bean으로 주석이 지정된 메서드의 본문에는 인스턴스를 생성하는 데 필요한 로직이 있어야 합니다.
@Component and @Bean do two quite different things, and shouldn't be confused.
@Component (and @Service and @Repository) are used to auto-detect and auto-configure beans using classpath scanning. There's an implicit one-to-one mapping between the annotated class and the bean (i.e. one bean per class). Control of wiring is quite limited with this approach, since it's purely declarative.
@Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically as above. It decouples the declaration of the bean from the class definition, and lets you create and configure beans exactly how you choose.
To answer your question...
would it have been possible to re-use the @Component annotation instead of introducing @Bean annotation?
Sure, probably; but they chose not to, since the two are quite different. Spring's already confusing enough without muddying the waters further.
@Component와 @Bean은 상당히 다른 기능을 수행하며 서로 혼동되어서는 안됩니다.
@Component (그리고 @Service와 @Repository)은 클래스 패스 스캔을 사용하여 자동으로 빈을 감지하고 구성하는 데 사용됩니다. 어노테이트된 클래스와 빈 간에는 암시적인 일대일 매핑이 있습니다(즉, 한 클래스당 하나의 빈). 이 방법으로 제어할 수 있는 와이어링의 범위는 매우 제한적입니다. 왜냐하면 이것은 순전히 선언적이기 때문입니다.
@Bean은 위에서 설명한 것과 같이 Spring이 자동으로 수행하는 대신에 명시적으로 하나의 빈을 선언하는 데 사용됩니다. 이 방법은 빈의 선언을 클래스 정의와 분리시켜주며, 빈을 만들고 구성하는 방법을 완전히 자유롭게 할 수 있습니다.
그래서 이제 질문에 답해보자면...
@Bead 어노테이션을 도입하는 대신 @Component 어노테이션을 재사용하는 것이 가능했을까?
그렇습니다. 아마 가능했을 것입니다. 그러나 두 어노테이션은 상당히 다르기 때문에, 이 둘을 혼동하면 안되기 때문에 이렇게 선택한 것입니다. Spring은 이미 혼란스러운데 더 혼란을 야기시키는 것은 좋지 않습니다.