빈(Bean)
- Spring IoC Container가 관리하는 자바 객체
- ApplicationContext가 알고있는 객체 (ApplicationContext.getBean()으로 얻어질 수 있는 객체)
- Bean만 의존성 주입이 된다.
Bean 등록
- Component Scanning
- Bean 설정파일에 직접 등록
Component Scan
원리
스프링에는 @Component 가 붙어있는 모든 클래스를 찾아서 클래스 인스턴스를 만들고 Bean으로 등록하는 Annotation Processor가 있다.
스프링부트는 main 메소드가 선언된 클래스를 기준으로 실행한다.
1
2
3
4
5
6
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
해당 클래스의 @SpringBootApplication
은 스프링 부트의 가장 기본적인 선언을 설정한다.
- @SpringBootApplication 내의 @ComponentScan은 어노테이션을 스캔하여 Bean으로 등록해주는 어노테이션이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
// ... 생략 ...
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@ComponentScan
이 붙어있는 위치에서부터 하위 패키지에 있는 모든 클래스를 찾아본다. (@ComponentScan은 어느 지점부터 찾을지 알려주는 것)@Component
가 붙어있는 클래스를 찾아서 Bean으로 등록한다.@Component을 사용하는 Annotation
- @Repository
- @Service
- @Controller
- @Configuration
- 등
Repository가 Bean으로 등록되는 과정 (JPA가 제공하는 기능에 의해 등록)
1
public interface MemberRepository extends JpaRepository<Member, Long>{
- 특정한 Annotation이 없더라도 Repository를 상속받은 경우 그 구현체를 찾아서 내부적으로 만들고 Bean으로 등록한다.
등록방법
@Component 혹은 @Component을 사용하는 Annotation을 Class 위에 작성
1
2
@Controller
public class CartController {
Bean 설정파일에 직접 등록
- Bean 설정파일
- xml
- java
Java 설정파일
1
2
3
4
5
6
7
8
9
@Configuration
public class SampleConfig {
@Bean
public SampleController sampleController() {
return new SampleController();
}
}
- 설정 클래스에
@Configuration
사용 - 객체를 return하는 메소드 위에
@Bean
사용 (return 하는 객체가 Bean으로 등록된다.)
Bean 주입하기
Bean을 주입할 수 있는 위치
생성자
1 2 3 4 5 6 7 8 9 10 11 12
@Controller class SampleController { private final SampleRepository sample; @Autowired public SampleController(SampleRepository sample) { this.sample = sample; } // ... 생략 }
이러한 경우 스프링 4.3 이상부터
@Autowired
를 생략할 수 있다.필드
1 2 3 4 5 6 7 8
@Controller class SampleController { @Autowired private SampleRepository sample; // ... 생략 }
setter
1 2 3 4 5 6 7 8 9 10 11 12
@Controller class SampleController { private SampleRepository sample; @Autowired public void setSample(SampleRepository sample) { this.sample = sample; } // ... 생략 }
IoC Container가 SampleController 인스턴스를 만들고 나서 setter를 통해 IoC Container에 들어있는 Bean 중에 SampleRepository의 의존성을 주입한다.
- Bean으로 등록되지 않은 경우 의존성을 주입하지 못한다.
Spring Framework Reference에서 권장하는 것은 생성자를 사용하는 방법이다.
- 의존성으로 주입되는 객체 없이는 생성될 수 없도록 강제할 수 있는 가장 좋은 수단이기 때문이다. (예 : SampleRepository 없이는 SampleController가 생성될 수 없도록 한다.)
- 필드, setter에서는 의존성 주입이 안되더라도 인스턴스를 만들 수 있다.
- 순환 참조(A -> B -> A)가 발생할 수 있는 문제를 해결할 수 있다. (가급적이면 발생하지 않도록 하기)
Bean 주입 Annotation
@Resource | @Inject | @Autowired | |
---|---|---|---|
의존 | Java | Javax | Spring |
사용 가능 위치 | - 필드 - 파라미터가 한 개인 setter | - 필드 - 생성자 - setter | - 필드 - 생성자 - setter |
Bean 검색 우선순위 | 이름 👉 타입 | 타입 👉 이름 | 타입 👉 이름 |
Bean 강제 지정 | @Resource(name=”ID”) | @Inject @Named(“ID”) | @Autowired @Qualifier(“ID”) |
Bean 없을 경우 | 예외 발생 | 예외 발생 | @Autowired(required=false) 처리하면 예외 발생 방지 |