스프링 프레임워크의 핵심적인 역할 중 하나는 의존성 주입(Dependency Injection)을 통해 객체 생성과 관리 책임을 개발자 대신 수행하는 것입니다.
이러한 역할을 가능하게 하는 주체가 ApplicationContext, 즉 스프링의 IoC 컨테이너입니다.
이 글에서는 스프링이 애플리케이션 실행 시 어떻게 컴포넌트를 탐색하고, 어떤 방식으로 빈을 등록하는지를 정리했습니다.
또한 @Component와 @Bean이 각각 어떤 상황에서 사용되는지, 자동 구성과 명시적 설정의 차이도 작성하였습니다.
- 스프링은 의존성 주입(DI)을 통해 객체 생성과 관리를 개발자 대신 수행함
- 이 역할을 담당하는 주체는 ApplicationContext, 즉 IoC(의존성주입) 컨테이너
- 애플리케이션 실행 시, 스프링이 컴포넌트를 어떻게 탐색하고 빈을 등록하는지 정리함
- @Component와 @Bean의 사용 상황을 비교
- 자동 구성 vs 명시적 설정의 차이도 함께 설명
1. ApplicationContext (애플리케이션 컨텍스트)
- 스프링의 IoC(의존성주입) 컨테이너 오브젝트
- 객체 생성을 개발자가 아닌 스프링이 관리 (new 키워드 사용 불필요)
- 설정 방식:
- 애노테이션 기반
- XML 기반
- 자바 기반
2. 스프링이 자바 빈을 등록하는 방법
2.1 스프링 자바빈 등록 절차
- 애플리케이션 시작 시, 스프링 부트가 자동 설정 실행
- @ComponentScan이 설정된 경우, 베이스 패키지 이하에서 @Component가 붙은 클래스를 탐색
- 찾은 클래스에 대해 객체를 생성하고 필요한 의존성을 주입
- @Component 붙은 클래스는 스프링이 직접 인스턴스를 생성
- @Configuration 붙은 클래스는 @Bean 이 붙은 메서드를 호출해 반환된 객체를 빈으로 등록
2.2 @Component
- 컴포넌트 스캔 대상으로 등록되어 @ComponentScan에 의해 자동으로 빈으로 등록 됨
- 개발자가 직접 작성한 클래스에 사용
- @Component 정의
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component
2.3 @Bean
- 외부 라이브러리 등 직접 수정할 수 없는 클래스의 객체를 빈으로 등록할 때 사용
- 클래스에 직접 붙일 수 없고, @Configuration 클래스 내부의 메서드에 선언해 사용
- @Bean 정의
//Target이 METHOD 이므로 클래스에 직접 붙일 수 없다.
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean
- Bean 사용 예시
- JPAQueryFactory는 외부 라이브러리(QueryDSL) 클래스이기 때문에 직접 @Component를 붙일 수 없다.
- EntityManager는 스프링이 관리하고 주입해주므로, 이를 활용해 인스턴스를 생성해야 한다.
- 생성자 주입(@RequiredArgsConstructor)으로 EntityManager를 받아 사용
- @Bean을 통해 명시적으로 JPAQueryFactory를 빈으로 등록
@Configuration
@RequiredArgsConstructor
public class QuerydslConfig {
private final EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
3. 참고
3.1 @Configuration이란?
- 해당 클래스를 스프링의 설정 클래스로 등록
- @Bean 메서드를 통해 직접 정의한 객체(빈)를 스프링 컨테이너에 등록
- 내부적으로 @Component가 포함되어 있어 컴포넌트 스캔 대상이 됨
- @Bean 메서드 호출 시 싱글톤 보장. 참고로,Component는 내부 메서드 간 호출 시 싱글톤을 보장하지 않는다.
3.1.1 @Configuration
- 내부적으로 CGLIB 프록시가 적용됨
- @Bean 메서드 간 호출 시, 스프링컨테이너에서 관리하는 빈을 반환
- 결과적으로 싱글톤이 유지됨
@Configuration
public class AppConfig {
@Bean
public A a() {
return new A(b()); // 실제로는 getBean("b")가 호출됨
}
@Bean
public B b() {
return new B();
}
}
3.1.2 @Component
- 프록시 적용되지 않음
- @Bean 메서드 간 호출 시, 단순 메서드 직접 호출로 처리됨
- 결과적으로 매번 새로운 인스턴스가 생성되어 싱글톤이 깨질 수 있음
3.2 어노테이션 생성 시 @Target
속성 의미
ElementType.TYPE | 클래스, 인터페이스, enum에 사용 가능 |
ElementType.METHOD | 메서드에 사용 가능 |
ElementType.ANNOTATION_TYPE | 다른 애노테이션을 꾸미는 데 사용 가능 |
@Bean의 정의에 ElementType.ANNOTATION_TYPE이 포함된 의미는 다른 커스텀 애노테이션이 @Bean을 메타 애노테이션으로 사용할 수 있다.
'Spring Framework > Spring' 카테고리의 다른 글
Spring Event 를 활용한 예약 푸쉬 발송 (0) | 2023.04.05 |
---|---|
Spring Security 디버깅 방법 (0) | 2023.03.30 |
스프링 시큐리티 DelegatingFilterProxy, FilterChainProxy (0) | 2023.02.15 |
스프링부트 버젼 - 마이너 버전 (0) | 2022.06.01 |
WebMvcConfigurer (0) | 2022.04.18 |
댓글