[Spring Basic] IoC와 DI 구조
변경이 쉬운 코드를 작성하기 위해 Properties클래스를 사용한다.
여기서 Properties는 key - value 쌍으로 값을 저장하고, 타입은 <String, String> 을 사용한다.
Properties클래스는 load메서드를 사용해 파일의 값을 읽어오거나 저장할 때 편리하게 사용될 수 있다.
AppContext클래스를 사용해 여러 객체를 저장하는 저장소를 구현한다.
내부적으로 Map 자료구조를 가지고 있어 키 값을 통해 객체의 value를 얻도록 설계돼있다.
스프링은 자바 객체들을 빈으로 관리하고, 필요할 때 주입해주는 컨테이너이다.
JavaBeans 기술은 원래 프론트엔드에서 GUI를 다룰 때 사용되는 기술이였지만 JavaFx로 업데이트하면서 자바로 GUI부분을 잘 사용하지 않게 되고 서버를 다루는데에 JavaBeans를 활용하게 됐다
이후 Enterprise Java Beans가 등장하고 여러 개발자들이 EJB를 배우게 되며 대세가 EJB로 기우는 듯 했지만..
EJB보다 훨씬 간단한 규칙을 가진 Spring 기술이 도입되고 EJB와 반대되는 Plain Old Java Object를 앞세워 자바 객체를 빈으로 등록해 컨테이너로 관리하는 기술인 스프링이 조명받게 됐다.
스프링은 Bean을 저장하고 관리하는 역할을 한다.
BeanFactory를 통해 Bean을 관리하는 기본 기능을 정의해두고, 이를 확장해 ApplicationContext만들고 다양한 기능을 정의했다. (ApplicationContext = Spring container)
스프링이 제공하는 빈을 통해 개발자는 객체의 생명주기와 의존성 관리 등의 부담에서 벗어나 비즈니스 로직에 집중해서 개발할 수 있게 됐다.
스프링을 사용하면 애플리케이션의 제어 흐름을 스프링이 가져간다.
객체를 빈으로 등록해서 관리하고 객체의 생성, 생명주기, 소멸, 의존성 주입 등 원래는 개발자가 직접 처리해야 되는 부분을 스프링이 대신 처리한다.
이를 Inversion Of Control, Dependency Injection 이라고 부른다.
스프링은 내부적으로 ApplicationContext 인터페이스의 구현체를 사용해 자바 객체를 빈으로 등록하고 관리한다.
(스프링 부트를 사용하더라도 내부적으로는 ApplicationContext 구현체를 사용한다)
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
}
...
}
@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>(8);
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
...
}
ApplicationContext 인터페이스의 구현체인 GenericApplicationContext 객체의 일부이다.
ConcurrentHashMap 구현체를 사용해 멀티쓰레드 환경에서 여러 쓰레드가 Map에 접근하더라도 데이터를 일관성을 유지하면서 자바 객체를 빈으로 관리한다. (빈의 이름을 Key 빈의 인스턴스를 Value로 관리한다)
자바 객체를 빈으로 등록하는 방법으로는 3가지가 있다.
스프링 애플리케이션의 시작은 ApplicationContext의 초기화이다.
1. xml
<bean id="beanName" class="beanClass">
이런 방식으로 빈을 등록해두면 애플리케이션이 시작될 때 스프링이 해당 xml 파일을 읽고 ApplicationContext에 빈을 저장한다.
2. ComponentScan
@Component 애너테이션으로 등록된 빈을 @ComponetScan 애너테이션으로 탐색하고 ApplicationContext에 빈을 저장한다.
3. @Configuration
@Configuration 클래스는 해당 클래스가 스프링 설정 관련 정보를 가지고 있음을 의미한다.
애플리케이션이 시작될 때 해당 클래스를 읽고 ApplicationContext에 빈을 저장한다.
스프링 MVC에서 디스패처 서블릿은 자체적으로 WebApplicationContext를 가진다.
WebApplicationContext는 ApplicationContext의 자식 컨텍스트로, ApplicationContext는 애플리케이션 전체를 위한 컨텍스트이고 WebApplicationContext는 디스패처 서블릿을 위한 컨텍스트이다.
어떻게 보면 스프링 컨테이너 (ApplicationContext) 내부에 서블릿에 특화된 작은 스프링 컨테이너 (WebApplicationContext) 가 있는 것으로 생각할 수 있는데, 이런 구조는 빈 관리와 설정의 일관성을 유지하기 위한 구조이다.
웹 애플리케이션에서 전체의 설정과 리소스는 공유되어야 하고, 서로 다른 서블릿들이 독립적으로 작동하는것도 가능해야 한다.
따라서 ApplicationContext가 전체적인 설정과 리소스 관리를 수행하고, 웹과 관련된 특정 리소스나 설정은 각 디스패처 서블릿 (WebApplicationContext) 이 수행하도록 설계한다.
스프링 내부에 또 스프링이 있는 것으로 볼 수 있지만, 각 컨테이너의 역할과 범위는 명확하게 분리되어있다.
이런 구조로 설계함으로 유지보수와 확장성을 향상시킨다.
빈을 주입할 때 애너테이션을 사용하면 편하다.
@Autowired 애너테이션을 사용하면 AppContext의 값들에 대해 해당 애너테이션이 붙은 타입이 있는지를 찾고, 찾으면 참조변수에 자동으로 대입해준다.
즉, 타입(값)을 통해 연결해준다.
@Resource 애너테이션을 사용하면 AppContext의 키에 대해 해당 애너테이션이 붙은 이름이 있는지를 찾고, 찾으면 참조변수에 자동으로 대입해준다. (이름은 첫 글자를 소문자로 바꾼 값으로 사용하거나, 따로 지정해 줄 수 있다.)
즉, 이름(키)를 통해 연결해준다.
'Spring > Spring' 카테고리의 다른 글
[Spring] 템플릿 메서드 패턴과 전략 패턴 (0) | 2023.07.19 |
---|---|
[Spring] 로그 추적기와 쓰레드 로컬 (0) | 2023.07.16 |
[Spring Basic] 웹 서버와 웹 애플리케이션 서버의 구조 (1) | 2023.06.14 |
[Spring Basic] 예외처리 (0) | 2023.06.13 |
[Spring Basic] 로그 (0) | 2022.08.16 |
댓글
이 글 공유하기
다른 글
-
[Spring] 템플릿 메서드 패턴과 전략 패턴
[Spring] 템플릿 메서드 패턴과 전략 패턴
2023.07.19 -
[Spring] 로그 추적기와 쓰레드 로컬
[Spring] 로그 추적기와 쓰레드 로컬
2023.07.16 -
[Spring Basic] 웹 서버와 웹 애플리케이션 서버의 구조
[Spring Basic] 웹 서버와 웹 애플리케이션 서버의 구조
2023.06.14 -
[Spring Basic] 예외처리
[Spring Basic] 예외처리
2023.06.13