😅 우선 글을 작성하기에 앞서 이 글은 스프링을 처음 공부하는 입장에서 Spring 공식 문서를 자의적으로 해석한 글이며 (번역기의 도움을 받아) 제게 필요하다고 생각되는 부분을 우선적으로 해석할 예정이라 중간중간 빈 부분이 있을 수 있으며 틀린 내용이 포함되었을 수 있습니다. 잘못된 부분이 있을 때 피드백 남겨주시면 능력껏 반영하도록 하겠습니다.
1. IoC 컨테이너
1. 1 Spring IoC 컨테이너 및 Bean 소개
이 장에서는 Inveresion of Control(IoC) 원칙을 구현하는 Spring Framework를 다룹니다. IoC는 종속성 주입(DI)이라고도 합니다. 종속성은 객체가 다른 객체의 생성자나, 팩터리 메서드의 인수로 넘겨지거나 다른 객체 내부의 인스턴스로 선언될 때 발생하는 프로세스입니다. 그런 다음 컨테이너는 bean을 생성할 때 이러한 종속성을 주입합니다.
org.springframwork.beans와 org.springframework.context 패키지는 Spring FrameWork의 IoC container의 기본 구성 요소입니다. 구체적으로 BeanFactory 인터페이스가 어떤 타입의 객체라도 관리할 수 있는 향상된 인식 메커니즘을 제공합니다. ApplicationContext는 BeanFacotry의 하위 인터페이스로써 다음의 기능이 추가되었습니다.
- Spring AOP 기능과의 더 쉬운 통합
- 메시지 리소스 핸들링
- Event publication
- 스프링에서, 빈(bean)은 어플리케이션의 뼈대를 형성하는 객체이며 Spring IoC 컨테이너에 의해 관리를 받습니다. 빈의 생성과 관리, 빈들 사이의 의존성 주입들은 컨테이너에서 사용하는 **구성 메타데이터(configuration metadata)**에 반영됩니다.
1.2 Container Overview
org.springframewokr.context.ApplicationContext 인터페이스는 IoC 컨테이너를 만들고, 구축하고, 빈들을 관리하는 책임을 가집니다. 컨테이너는 어떤 객체들을 만들고, 관리해야되는지 구성 메타데이터에서 정보를 얻어옵니다. 구성 메타데이터는 XML, Java annotation, 혹은 Java code에 표현되어 있습니다.
ApplicationContext는 구성 메타데이터를 반들어주는데 일반적으로, ClassPathXmlApplicationContext나 FileSystemXmlApplicationContext를 통해 인스턴스가 만들어지게 됩니다. XML은 전통적으로 메타데이터를 작성하는 포맷이지만, Java 어노테이션이나 자바 코드 자체를 이용하여 메타데이터를 구성할 수 있도록 기능을 제공합니다. 다음 아래의 그림은 Spring이 어떻게 작동하는지에 대해 설명해줍니다. 당신이 만든 어플리케이션은 ApplicationContext를 통해 초기화된 후 구성 메타데이터와 결합하여 웹에서 실행가능한 시스템이 됩니다.
1.2.1 Configuration Metadata(구성 메타데이터)
구성 메타데이터는 스프링 컨테이너에게 당신이 만든 어플리케이션의 객체들을 어떻게 초기화하고 구성하며, 조합해야 하는지 알려줍니다. 구성 메타데이터는 전통적으로 직관적인 XML 포맷을 통해 구성됩니다. (최근에는 XML 포맷뿐만 아니라 자바 기반 포맷을 사용하는 경우가 많습니다.)
- Annotation-based configuration : annotation 기반으로 구성 메타데이터를 작성하고 빈을 생성
- Java-based configuration : 자바 코드에 @Configuration, @Bean 등의 어노테이션을 붙이면 빈을 생성
- 구성 메타데이터의 빈 정의는 애플리케이션을 구성하는 실제 개체에 해당합니다. 이를 위해 서비스, 컨트롤러, DAO 등의 어노테이션이 사용됩니다. 또한 일반적으로 구체적인 도메인의 객체들을 하나하나 빈으로 만드는 경우는 거의 없습니다. 이는 비즈니스 로직의 책임으로 보기 때문입니다.
1.2.2 Instantiating a Container
AplicationContext constructor에 제공되는 위치 경로는 컨테이너가 외부 리소스에서 구성 메타데이터를 로드할 수 있도록 CLASSPATH를 문자열로 제공합니다.
1.3 Bean Overview
빈들은 Spring IoC container에 의해 만들어지고 관리됩니다. 컨테이너 내부에서 이러한 빈들의 정의는 BeanDefinition 객체를 통해 저장되어 있는 메타데이터를 찾아볼 수 있습니다.
- Class, Name, Scope, Constructor arguments, Properties ,Autowiring mode, Lazy initialization mode, Initialization method, Destruction method
- 참고로 ApplicationContext는 또한 컨테이너 외부에 생성된 객체의 등록도 허용한다.
1.3.2 Instantiating Beans
빈 정의는 기본적으로 하나 이상의 객체를 생성하기 위한 레시피입니다. 컨테이너는 요청될 때 명명된 빈에 대한 레시피를 보고 해당 빈 정의에 의해 캡슐화된 구성 메타데이터를 사용하여 실제 개체를 생성합니다.
XML 기반 구성 메타데이터를 사용한다면, 객체가 어떤 타입으로 만들어질지는 <bean/> 내부의 class 속성에서 지정합니다. Class 속성은 다음 두 가지 방법으로 사용할 수 있습니다.
- 일반적으로 컨테이너는 클래스의 생성자를 (ex. new Class();) 반사적으로 호출하여, 빈을 생성합니다. (Constructor)
- 정적 팩토리 메서드를 포함하는 클래스의 경우 (Static Factory Method)
Instantiation with a Constructor
생성자를 통해 빈을 생성하면 모든 일반 클래스가 Spring에서 사용 가능하고 호환됩니다. 따라서, 당신이 작성하려는 클래스들이 특정한 인터페이스를 구현하거나 특정한 형식을 따라 작성되어야 할 필요가 없습니다. Spring IoC 컨테이너는 거의 모든 클래스를 관리할 수 있습니다.
XML 기반 구성 메타데이터를 사용하여 다음과 같이 빈 클래스를 지정합니다.
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
Instantiation with a Static Factory Method
정적 팩토리 메서드를 사용하여 빈을 정의할 때 정적 팩토리 메서드가 포함된 클래스의 class 속성을 정의해주고, factory-method 속성에서 정적 팩토리 메서드의 네이밍을 명시해주어야합니다. 해당 메서드를 통해서 실제 객체가 반환되어야 하고, 그 객체는 생성자를 통해 생성되는 객체인 것처럼 처리됩니다.
다음은 정적 팩토리 메서드를 사용한 경우의 구성 메타데이터 예시입니다.
<bean id="clientService"
class="examples.ClientService"
factory-method="createInstance"/>
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}
public static ClientService createInstance() {
return clientService;
}
}
Instantiation by Using an Instance Factory Method
정적 팩토리 메서드를 통해 빈을 생성하는 방법과 비슷하게, 빈을 생성하기 위해 컨테이너에 이미 존재하는 빈의 인스턴스 팩토리 메서드를 호출하는 방식이다. 이 방식을 사용하기 위해서는 class 속성을 비워두고, factory-bean 메서드에 인스턴스 팩토리 메서드가 존재하는 클래스의 이름을 명시한다. 마지막으로 factory-method 속성에 팩토리 메서드의 이름을 적어준다. 다음은 예시다.
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<!-- the bean to be created via the factory bean -->
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
public ClientService createClientServiceInstance() {
return clientService;
}
}
'Spring' 카테고리의 다른 글
@DirtiesContext를 사용하지 않고 테스트 데이터베이스 초기화하기 (0) | 2023.07.16 |
---|---|
[Spring 공식문서] Spring Core 1.5 (0) | 2023.05.07 |
[Spring 공식문서] Spring Core 1.4 (0) | 2023.04.30 |
[Spring] DAO는 어떤 값을 주고 받아야 할까?(DAO, DTO, Entity) (2) | 2023.04.20 |