개요
개인프로젝트를 진행하면서, ApplicationContext로 직접 빈을 호출하여 사용한 부분이 있었습니다. 스프링 컨테이너를 관리하는 중요한 인터페이스이다 보니, 스프링 IoC 컨테이너와 스프링 빈도 관련된 내용을 정리했습니다.
Application & BeanFactory
The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds:
Easier integration with Spring’s AOP features
Message resource handling (for use in internationalization)
Event publication
Application-layer specific contexts such as the WebApplicationContext for use in web applications.
In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory and is used exclusively in this chapter in descriptions of Spring’s IoC container. For more information on using the BeanFactory instead of the ApplicationContext, see the section covering the BeanFactory API.
- The org.springframework.beans와 org.springframework.context는 스프링 IoC 컨테이너의 핵심
- BeanFactory는 기본 기능을 제공하지만 ApplicationContext는 더 많은 기능을 지원
- ApplicationContext는 BeanFactory의 구현체로 사실상 스프링 IoC 컨테이너와 동일
- 스프링 AOP 쉬운 통합
- 국제화 메세지 자원 관리
- 이벤트 발행
- 웹어플리케이션에서 WebApplicationContext 같은 context
BeanFactory와 ApplicationContext 인터페이스 정의는 다음과 같습니다.
//BeanFactory 인터페이스
public interface BeanFactory {
...
}
//ApplicationContext 인터페이스
public interface ApplicationContext extends EnviromentCapable, ListableBeanFactory,
HierachicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
...
}
자바 설정 클래스를 기반으로 스프링 컨테이너를 다음 방식으로 생성할 수 있습니다.
ApplicationContext ac = new AnnotationConfigApplicationContext(App.Config.class);
ApplicationContext
The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It lets you express the objects that compose your application and the rich interdependencies between those objects.
- ApplicationContext는 스프링 IoC 컨테이너
- 메타 데이터를 확인하여 어떤 객체를 인스턴스화하고, 구성하고, 조립할지 결정
- 어플리케이션을 구성하는 객체들과 객체들의 상호 의존성을 메타데이터로 표현
- 메터데이터는 XML, Java annotation, Java code로 표현
다음 다이어그램은 스프링 작업의 추상화 다이어그램입니다. 어플리케이션 클래스들과 메타데이터는 결합하고, ApplicationContext가 생성 및 초기화되면, 실행가능한 시스템이 됩니다.
스프링 IoC 컨테이너의 빈들을 객체로 만드는데 많은 코드가 필요하지 않습니다. 예를 들어 웹 어플리케이션에서 약 8줄의 웹 기술서 web.xml만 있면 충분합니다.
메타데이터 설정
이전 다이어그램에 따르면, 스프링 IoC 컨테이너는 구성 메타데이터 형식을 사용합니다. 개발자들은 어플리케이션에 있는 객체들을 어떻게 인스턴스화하고 구성하고 조립하는지 스프링 컨테이너에게 알려주기 위해 메타데이터를 사용합니다.
메타데이터 설정은 과거에 XML 형식으로 많이 작성되었습니다. 하지만 최근에는 자바 기반 어노테이션을 많이 사용합니다.
XML 기반 ApplicationContext 초기화하기
다음은 ContextLoaderListener를 통해서 ApplicationContext를 생성하는 방식입니다.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
리스너는 contextConfigLocation 매개변수를 검사합니다. 만약에, 매개변수가 없다면 리스너는 기본 경로로 /WEB-INF/applicationContext.xml를 사용합니다. 매개변수가 있다면, 리스너는 해당 경로의 XML을 확인합니다. 만약 /WEB-INF/*Context.xml라고 설정하면, Context.xml로 끝나는 모든 파일을 조사합니다.
ApplicationContext는 빈을 관리하는 역할을 하기 때문에, 빈에 대한 이해가 필요합니다.
스프링 컨테이너 라이프사이클
스프링 컨테이너 라이프사이클 과정을 큰 흐름에서 보여주는 그림입니다.
- 스프링 빈 인스턴스화와 동시에 생성자 의존관계 주입
- Setter 추가 의존관계 주입
- *Aware는 콜백으로 각종 스프링의 내부 객체 접근을 허용하는 인터페이스입니다.
- *Aware을 구현한 빈은 ApplicationContext, BeanFactory 등을 사용할 수 있습니다.
- 예를 들어, BeanFactoryAware 구현체는 setter 주입으로 BeanFactory을 얻습니다.
- ServletContextAware 구현체는 setter 주입으로 ServletContext을 얻습니다.
- InitializingBean, @PostConstruct, @Bean(initMethod = "init") 등 생명주기 콜백을 통한 초기화, 소멸화 콜백 사용
스프링 빈(Bean)
스프링 빈은 스프링 컨테이너가 인스턴스화하고 조립하고 관리하는 객체입니다.
과연 어플리케이션의 객체를 모두 스프링 빈으로 등록해야할까요? 꼭 그렇지는 않습니다.
스프링 공식문서에 따르면, 서비스 계층 객체, 데이터 접근 객체(DAO), 프리젠테이션 객체, Hibernate SessionFactories 같은 인프라 객체를 빈으로 정의해야 합니다.
위에서 말했듯이, ApplicationContext의 가장 중요한 특징은 빈을 관리하는 것입니다. 빈 설정 방식은 크게 3가지로, 자바 코드 기반, 어노테이션 기반, XML 기반 설정이 있습니다.
1. 자바 코드 기반
보통 메서드에 @Bean을, 클래스에 @Configuration을 사용하여 자바설정을 합니다.
메서드에 붙여진 @Bean 어노테이션은 스프링 빈을 생성하는 메서드입니다.
또한, @Configuration이 붙여진 클래스는 스프링 빈 설정을 포함한다고 알려주는 역할을 합니다.
@Configuration
public class AccountConfig {
@Bean
public AccountService accountService() {
return new AccountService(accountRepository());
}
@Bean
public AccountRepository accountRepository() {
return new AccountRepository();
}
}
2. 어노테이션 기반
자바에서 빈 설정을 하는 방법으로 스프링 2.5버전에서 어노테이션 기반 설정을 소개했습니다.
처음에는 xml 설정으로 어노테이션 기반 설정이 가능했는데, 자바 클래스, 메서드, 생성자, 필드에서도 설정을 많이 합니다. 예를들어 @Component, @Controller, @Service, @Repository, @Autowired, @Qualifer 등을 사용할 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.baeldung.applicationcontext"/>
</beans>
annotation-config는 어노테이션 기반 매핑을 활성화합니다. 또한 component-scan은 Spring에 주석이 달린 클래스를 찾을 위치를 알려줍니다.
@Component
public class UserService {
// user service code
}
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationcontext/user-bean-config.xml");
UserService userService = context.getBean(UserService.class);
assertNotNull(userService);
@Component
public class UserService {
// user service code
}
3. XML 기반
스프링에서 빈을 설정하는 전통적인 방법입니다. XML파일에서 모든 빈 설정을 할 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountService" class="com.baeldung.applicationcontext.AccountService">
<constructor-arg name="accountRepository" ref="accountRepository" />
</bean>
<bean id="accountRepository" class="com.baeldung.applicationcontext.AccountRepository" />
</beans>
Bean Scope
빈 스코프란 언제 빈 객체가 초기화되고, 얼마나 오래 살아있고, 얼마나 많은 객체가 생성되는지를 의미하는 빈의 생명주기.즉, 빈이 존재하는 범위입니다. 기본은 싱글턴이며, 빈의 인스턴스 생성은 스프링 컨테이너가 관리합니다.
빈 스코프를 통해, 스프링에서 특정 빈 정의로 생성된 객체에 주입되는 다양한 의존성을 설정 할 수 있을 뿐만 아니라, 특정 빈 정의로부터 생성된 객체의 스코프를 통제할 수 있습니다. 이 접근 방식이 좋은 이유는, 자바 클래스 수준에서 객체의 스코프를 조립 할 필요 없이 설정을 통해서 객체의 스코프를 선택할 수 있기 때문입니다. 빈들은 많은 스코프들 중에서 하나의 방식으로 생성되도록 할 수 있습니다. 스프링은 6개의 스코프를 지원하며, 4개는 web-aware ApplicationContext를 사용할 때만 가능합니다.
이외에 다음과 같은 스코프가 있습니다.
Prototype - 요구가 있을 때마다 새로운 빈을 만들어 리턴
request - HTTP request 당 하나의 빈 리턴
session - HTTP session 당 하나의 빈 리턴
globalSession - 포틀릿의 global Http Session 생명주기 동안 하나의 빈만 존재
* ApplicationContext 설정하기
스프링은 다양한 요구사항에 따라서 여러가지의 ApplicationContext 컨테이너 종류를 제공합니다. ApplicationContext 인터페이스의 구현체는 여러개가 있습니다.
*WebApplicationContext
WebApplicationContext는 스프링에서 웹과 관련된 어플리케이션 컨텍스트입니다.(서블릿 정보를 가지고 있습니다.) 싱글 웹 어플리케이션에서, 여러개의 WebApplicationContext가 있을 수 있습니다. 각각의 WebApplicationContext은 1개의 DispatcherServlet와 결합합니다. WebApplicationContext 설정 파일은 기본 이름이 *-servlet.xml이며 특정 DispatcherServlet을 가리킵니다.
WebApplicationContext는 ApplicationContext 인터페이스의 자식입니다. 컨테이너 객체가 자동으로 생성되기 때문에, ApplicationContext와 달리 컨테이너 객체를 명시적으로 생성하거나 제거할 필요가 없습니다.
DispatcherServlet을 이용하여 controller, viewResolver 등의 웹과 관련된 컴포넌트들을 다루는데 사용됩니다.
* 참고
https://stackoverflow.com/questions/19324964/beannameaware-and-beanfactoryaware
https://jstobigdata.com/spring/spring-bean-lifecycle-callbacks/
https://vcfvct.wordpress.com/2015/09/15/spring-ioc-life-cycle/
https://www.geeksforgeeks.org/singleton-and-prototype-bean-scopes-in-java-spring/
https://devmoony.tistory.com/113
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-metadata
https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring
'Spring' 카테고리의 다른 글
DI(Dependency Injection) (0) | 2022.07.14 |
---|---|
Servlet (0) | 2022.07.11 |
Spring framework 로그(log) 알아보기 (1) | 2021.12.16 |
네이버 지역검색 API를 활용한 맛집 List 제작 - (4) (0) | 2021.08.29 |
네이버 지역검색 API를 활용한 맛집 List 제작 - (3) (0) | 2021.08.22 |