[Spring] 여러 어노테이션들 (@Configuration, @Component, @ComponentScan, @Autowired, @Primary, @Qulifier, @Inject)
스프링 관련 여러 어노테이션 정리
@Configuration
Spring에서 설정 클래스임을 명시하는 어노테이션
@Bean으로 정의한 메서드들을 빈 객체로 등록한다.
내부적으로 @Component가 포함되어 있어 컴포넌트 스캔 대상이 됨
@Configuration 은 CGLIB 프록시로 감싸져서 @Bean 메서드가 서로 호출될때,
새로운 객체를 매번만들지 않고 싱글톤 보장을 위해 등록된 빈을 반환한다.
@Bean
public A a() { return new A(); }
@Bean
public B b() { return new B(a()); }
이렇게 하면 b()에서 a()를 직접 호출하여도 실제로는 스프링 컨테이가 관리하는 같은 A의 빈을 반환한다.
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserServiceImpl(userRepository());
}
@Bean
public UserRepository userRepository() {
return new JdbcUserRepository();
}
}
프링 컨테이너는 AppConfig를 통해 userService와 userRepository를 등록하고 DI까지 처리
@Component
일반적인 스프링 빈(Bean) 을 선언할 때 사용하는 애노테이션입니다. 가장 기본적인 컴포넌트 스캔 대상이며, 이 애노테이션이 붙은 클래스는 자동으로 Spring 컨테이너에 등록
클래스의 객체를 Spring 컨테이너에 자동 등록해준다.
클래스 상단에 선언하면 된다.
@Controller, @Service, @Repository는 모두 @Component의 세분화된 형태이다.
프록시로 감싸지지 않기에 그냥 일반 메서드 호출이 되어버린다. b()에서 a()를 호출하면
새로운 객체 A가 매번 생성된다.
**** 스프링이 객체를 빈으로 등록시에 프록시로 감싸는 이유
1. 싱글톤 보장
프록시를 중간에 삽입하여 메서드 호출을 가로채어 컨테이너에 있는 객체를 반환해준다.
2. aop(관점 지향 프로그래밍) 지원을 위해서
트랜잭션, 보안, 로깅 같은 횡단관심사 로직을 적용하기 위해서 프록시를 통해 코드 적용을 할 수 있다.
@ComponentScan
Spring이 @Component, @Service, @Repository, @Controller 등이 붙은 클래스를 자동으로 스캔해서 빈(Bean)으로 등록하도록 하는 설정 애노테이션
지정한 패키지 및 하위에서 컴포넌트 클래스(@Component 계열)를 자동으로 스캔
@Configuration
@ComponentScan(basePackages = "com.example.project")
public class AppConfig {
}
//com.example.project 하위의 모든 @Component 계열 클래스를 스프링 컨테이너에 자동 등록
@Configuration
@ComponentScan
public class AppConfig {
}
//이 경우 AppConfig가 위치한 패키지와 그 하위 패키지 전체가 스캔 대상
//여러 패키지 동시 스캔
@ComponentScan(basePackages = {"com.example.service", "com.example.repository"})
@Primay
기본값으로 사용할 빈 지정
@Autowired로 주입할 때 후보 빈이 여러 개일 경우, @Primary가 붙은 빈을 우선적으로 선택
@Component
@Primary
public class EmailService implements MessageService {}
@Component
public class SmsService implements MessageService {}
@Qulifier
지정한 이름의 빈을 선택, 빈이 여러 개 존재할 때, 정확한 이름으로 특정 빈을 지정해서 주입할 수 있음.
@Component("emailService")
public class EmailService implements MessageService {}
@Component("smsService")
public class SmsService implements MessageService {}
@Inject
@Autowired와 같은 역할을 하는 표준 애노테이션입니다.
Spring에서도 동일하게 사용 가능하며, @Autowired의 대체제로 사용
@Inject
private MessageService messageService;
@Inject
@Named("smsService")
private MessageService messageService;
@Autowired
Spring Framework에서 **의존성 주입(Dependency Injection)**을 위해 사용되는 애노테이션
스프링 컨테이너가 @Autowired가 붙은 필드, 생성자, 메서드에 적절한 Bean을 찾아 자동으로 주입
필드주입 형태로 이루어진다.
@Component
public class OrderService {
@Autowired
private PaymentService paymentService; // 타입에 맞는 Bean 자동 주입
}
단점: 테스트가 어렵고, final 사용 불가
공식 문서에서는 생성자 주입 형태를 권고하고 있음.
@Component
public class OrderService {
private final PaymentService paymentService;
@Autowired // 생략 가능 (Spring 4.3+ 단일 생성자일 경우)
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}