ApplicationContext
- Spring Container 인터페이스
- 구현체 예시 목록
AnnotaionConfigApplicationContext
GenericXmlApplicationContext
GenericGroovyApplicationContext
StaticApplicationContext
- ISP (Interface Segregation Principle)
BeanFactory
- Bean을 관리하고 조회하는 역할
ListableBeanFactory
HierarchicalBeanFactory
EnvironmentCapable
- 로컬, 개발, 운영 등을 구분해서 환경변수를 관리하는 역할
ResourceLoader
- 파일, classpath, 외부 등에서 Resource를 관리하고 조회하는 역할
ResourcePatternResolver
MessageSource
- 메시지를 다국어로 처리하는 기능을 담당하는 역할
ApplicationEventPublisher
- 이벤트를 발행하고 구독하는 모델을 편리하게 지원하는 역할
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
}
ApplicationContext 클래스 다이어그램
다양항 설정 형식 지원
Spring Container 생성 과정
- Spring Bean을 생성한다.
- Spring Bean들의 의존관계를 주입한다.
Spring Container에 등록된 모든 Bean 조회
ApplicationContext::getBeanDefinitionNames()
: 등록된 모든 Bean 이름 조회
- 코드 예시
class ApplicationContextTests {
@Test
@DisplayName("Application Bean 출력하기")
void findApplicationBean() {
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition
= applicationContext.getBeanDefinition(beanDefinitionName);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = applicationContext.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + ", bean = " + bean);
System.out.println("beanDefinition = " + beanDefinition);
}
}
}
}
Spring Bean 조회
Bean 이름으로 조회
ApplicationContext::getBean(beanName)
- 해당 이름으로 등록된 Bean이 없는 경우
NoSuchBeanDefinitionException
예외 발생
- 코드 예시
Bean 이름, Bean 타입으로 조회
ApplicationContext::getBean(beanName, beanType)
- 코드 예시
Bean 타입으로 조회
ApplicationContext::getBean(beanType)
- 같은 타입의 Bean이 2개 이상 등록된 경우
NoUniqueBeanDefinitionException
예외 발생
- 코드 예시
동일한 타입 둘 이상의 Bean 조회
ApplicationContext::getBeansOfType(beanType)
: Map<String, T>
- 코드 예시
Spring Bean 조회 - 상속관계
- 부모 타입으로 조회하면, 자식 타입도 함께 조회한다.
- 코드 예시
BeanDefinition
- Bean의 메타데이터 정보를 담고 있는 인터페이스
BeanClassName
Bean Scope
- Scope :
int
- 기본값:
SCOPE_SINGLETON
SCOPE_SINGLETON
SCOPE_PROTOTYPE
Lazy Initialization
DependsOn
- DependsOn :
String[]
- 해당 Bean이 생성되기 전에 먼저 생성되어야 하는 Bean의 이름
Autowire Candidate
- AutowireCandidate :
boolean
- 해당 Bean을 다른 Bean의 의존성 주입 후보로 사용할지 여부
Primary
- Primary :
boolean
- 같은 타입의 Bean이 여러 개 등록된 경우, 우선권을 가지는 Bean을 설정
@Autowired
어노테이션을 사용할 때 우선권을 가지는 Bean을 주입한다.
Factory Bean Name, Factory Method Name
- FactoryBeanName :
String
- 해당 Bean을 생성하는 Factory Bean의 이름
- ex:
@Configuration
어노테이션을 가진 Bean의 이름
- FactoryMethodName :
String
- 해당 Bean을 생성하는 Factory Method의 이름
Constructor Argument Values, Property Values
- ConstructorArgumentValues :
ConstructorArgumentValues
- 생성자를 통해 Bean을 생성할 때 사용할 인자 정보
- PropertyValues :
MutablePropertyValues
Init Method Name, Destroy Method Name
- InitMethodName :
String
- DestroyMethodName :
String
Role
- Role :
int
ROLE_APPLICATION
: 일반적으로 사용자가 정의한 Bean
ROLE_INFRASTRUCTURE
: 스프링 내부에서 사용하는 Bean
ROLE_SUPPORT
Spring Container 와 Singleton Bean
- Spring Container는 기본적으로 모든 Bean을 Singleton으로 관리한다.
- Bean Scope 설정에 따라 다른 Lifecycle을 가진 Bean을 생성할 수 있다.
SCOPE_SINGLETON
SCOPE_PROTOTYPE
Singleton 방식의 주의사항
- Singleton 객체는 stateless 하게 설계해야 한다.
- 특정 클라이언트에 의존적인 필드가 있으면 안된다.
- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
- 가급적 읽기만 가능해야 한다.
- 공유되는 필드가 있다면, Thread-safe 하게 설계해야 한다.
- Local Variable, Method Parameter, ThreadLocal 등을 사용해야 한다.
@Configuration과 바이트코드 조작
@Configuration
어노테이션을 가진 Bean은 CGLIB 라이브러리를 사용하여 바이트코드를 조작한다.
- 만약
@Configuration
어노테이션을 제거한다면, Singleton Bean으로 등록되지 않는다.
- CGLIB 라이브러리를 통해 바이트코드 조작이 되지 않기 때문이다.
Reference: 스프링-핵심-원리-기본편 (인프런)