일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- MySQL
- 스프링
- Di
- reflection
- Varchar
- Lock
- gc
- Synchronized
- 동시성 문제
- 백엔드
- iterator
- java
- text
- 가비지 컬렉터
- foreach
- 가비지 컬렉션
- Locking Read
- 동시성
- Atomic Type
- jpa
- iterable
- CAS
- MVCC
- db
- 자바
- 데이터 타입
- Today
- Total
과정을 즐기자
내부 클래스를 스프링 빈으로 등록할 수 있을까? 본문
지금까지 톱 레벨 클래스에 @Controller, @Service, @Repository, @Component를 붙여 스프링 빈으로
등록하였습니다. 등록을 하면 스프링 컨테이너 안에서 기본적으로 싱글톤으로 관리됩니다.
이때 내부 클래스도 스프링 빈으로 등록할 수 있는 지 궁금증이 생겨 예제, 학습 테스트를 만들어봤습니다.
중첩 클래스는 정적 멤버 클래스, 비정적 멤버 클래스, 익명 클래스, 지역 클래스 4가지로 나뉩니다.
여기서 정적 멤버 클래스를 제외한 나머지 클래스 들을 내부 클래스라고 부릅니다.
Hello 라는 톱 레벨 클래스 안에 4가지 중첩 클래스를 만들어보았습니다.
// 톱 레벨 클래스
@Component
public class Hello {
// 정적 멤버 클래스
@Component
static class World1 {
}
// 비정적 멤버 클래스
@Component
class World2 {
}
// 익명 클래스 - 아예 @Component 사용 불가
Runnable anonymousClass = new Runnable() {
@Override
public void run() {
// 익명 클래스의 구현 내용
}
};
public void helloWorld() {
// 지역 클래스
@Component
class World3 {
}
}
}
정적 멤버 클래스, 비정적 멤버 클래스, 지역 클래스는 @Component를 붙여도 컴파일 에러가 발생하지 않았지만
익명 클래스는 아예 @Component를 사용할 수 없습니다.
어떻게 보면 이름을 가지지 않는 익명 클래스이기 때문에 당연한 결과입니다.
이제 학습 테스트를 보겠습니다.
@SpringBootTest
class HelloTest {
@Autowired
private AnnotationConfigApplicationContext ac;
@Test
@DisplayName("static 클래스는 스프링 빈으로 등록될 수 있지만 내부 클래스는 빈으로 등록될 수 없습니다")
void test() {
assertThat(ac.getBean("hello")).isNotNull();
assertThat(ac.getBean("hello.World1")).isNotNull();
assertThatThrownBy(() -> ac.getBean("hello.World2"))
.isInstanceOf(NoSuchBeanDefinitionException.class);
assertThatThrownBy(() -> ac.getBean("hello.World3"))
.isInstanceOf(NoSuchBeanDefinitionException.class);
}
}
위 테스트가 통과합니다. 즉 스프링 빈으로 등록된 클래스는 톱 레벨 클래스, 정적 멤버 클래스 입니다.
나머지 비정적 멤버 클래스, 익명 클래스, 지역 클래스는 스프링 빈으로 등록할 수 없습니다.
스프링 빈으로 등록할 수 없는 3가지 클래스의 공통점은 바로 내부 클래스 라는 것 입니다.
왜 내부 클래스는 스프링 빈으로 등록될 수 없을까요?
내부 클래스의 인스턴스는 바깥 인스턴스에 의존하기 때문입니다.
중첩 클래스 중에서 정적 멤버 클래스는 위치만 톱 레벨 클래스의 내부에 있는 것이지
바깥 인스턴스가 존재하지 않아도 독립적으로 인스턴스화 할 수 있습니다.
즉 정적 멤버 클래스는 독립적으로 인스턴스화를 할 수 있기 때문에 스프링 빈으로 등록할 수 있고
내부 클래스는 바깥 인스턴스에 의존하기 때문에 스프링 빈으로 만들 수 없습니다.
'Spring' 카테고리의 다른 글
바이너리 데이터를 처리하는 방법 (0) | 2023.10.28 |
---|---|
Spring과 Node.js 비교하기 (0) | 2023.08.26 |
이메일 전송 비동기로 처리하기 [Spring Boot] (0) | 2023.06.10 |
스프링에서 파일(이미지, 동영상) 업로드/다운로드 (0) | 2023.05.28 |
로컬 캐시를 적용하여 이메일로 전송하고자 하는 퀴즈 캐싱하기 (0) | 2023.05.03 |