Instantiating the Spring Container by Using AnnotationConfigApplicationContext

2024. 11. 14. 14:11Spring Framework/Spring IoC

다음 섹션에서는 Spring 3.0에 도입된 Spring의 AnnotationConfigApplicationContext를 설명합니다. 이 다재다능한 ApplicationContext 구현은 @Configuration 클래스뿐만 아니라 일반 @Component 클래스와 JSR-330 메타데이터로 어노테이션이 달린 클래스도 입력으로 허용할 수 있습니다.

@Configuration 클래스가 입력으로 제공되면 @Configuration 클래스 자체가 빈 정의로 등록되고 클래스 내에서 선언된 모든 @Bean 메서드도 빈 정의로 등록됩니다.

@Component 및 JSR-330 클래스가 제공되면 빈 정의로 등록되고 필요한 경우 @Autowired 또는 @Inject와 같은 DI 메타데이터가 해당 클래스 내에서 사용된다고 가정합니다.

 

Simple Construction

ClassPathXmlApplicationContext를 인스턴스화할 때 Spring XML 파일이 입력으로 사용되는 것과 거의 같은 방식으로 AnnotationConfigApplicationContext를 인스턴스화할 때 @Configuration 클래스를 입력으로 사용할 수 있습니다. 이렇게 하면 다음 예제에서 보듯이 Spring 컨테이너를 완전히 XML 없이 사용할 수 있습니다.

public static void main(String[] args) {
	ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
	MyService myService = ctx.getBean(MyService.class);
	myService.doStuff();
}

 

앞서 언급했듯이 AnnotationConfigApplicationContext는 @Configuration 클래스에서만 작동하는 데 국한되지 않습니다. 다음 예제에서 보듯이 @Component 또는 JSR-330 주석이 달린 클래스는 생성자에 입력으로 제공될 수 있습니다.

public static void main(String[] args) {
	ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
	MyService myService = ctx.getBean(MyService.class);
	myService.doStuff();
}

 

앞의 예제에서는 MyServiceImpl, Dependency1, Dependency2가 @Autowired와 같은 Spring DI 어노테이션을 사용한다고 가정합니다.

 

Building the Container Programmatically by Using register(Class<?>…​)

아규먼트가 없는 생성자를 사용하여 AnnotationConfigApplicationContext를 인스턴스화한 다음 register() 메서드를 사용하여 구성할 수 있습니다. 이 접근 방식은 AnnotationConfigApplicationContext를 프로그래밍 방식으로 빌드할 때 특히 유용합니다. 다음 예는 그 방법을 보여줍니다.

public static void main(String[] args) {
	AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
	ctx.register(AppConfig.class, OtherConfig.class);
	ctx.register(AdditionalConfig.class);
	ctx.refresh();
	MyService myService = ctx.getBean(MyService.class);
	myService.doStuff();
}

 

Enabling Component Scanning with scan(String…​)

컴포넌트 스캐닝을 활성화하려면 다음과 같이 @Configuration 클래스에 어노테이션을 달 수 있습니다.

@Configuration
@ComponentScan(basePackages = "com.acme")
public class AppConfig  {
	// ...
}

 

앞의 예에서 com.acme 패키지는 @Component 어노테이션이 달린 클래스를 찾기 위해 스캔되고, 해당 클래스는 컨테이너 내에서 Spring 빈 정의로 등록됩니다. AnnotationConfigApplicationContext는 다음 예에서 보여지는 것처럼 동일한 컴포넌트 스캔 기능을 허용하기 위해 scan(String…​) 메서드를 노출합니다.

public static void main(String[] args) {
	AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
	ctx.scan("com.acme");
	ctx.refresh();
	MyService myService = ctx.getBean(MyService.class);
}

 

@Configuration 클래스는 @Component로 메타 어노테이션이 달려 있으므로 컴포넌트 스캐닝의 후보입니다. 앞의 예에서 AppConfig가 com.acme 패키지(또는 그 아래의 패키지) 내에 선언되었다고 가정하면 scan()을 호출하는 동안 선택됩니다. Refresh() 시 모든 @Bean 메서드가 처리되고 컨테이너 내에서 빈 정의로 등록됩니다.

 

 

Support for Web Applications with AnnotationConfigWebApplicationContext

AnnotationConfigApplicationContext의 WebApplicationContext 변형은 AnnotationConfigWebApplicationContext와 함께 사용할 수 있습니다. 이 구현은 Spring ContextLoaderListener 서블릿 리스너, Spring MVC DispatcherServlet 등을 구성할 때 사용할 수 있습니다. 다음 web.xml 스니펫은 일반적인 Spring MVC 웹 애플리케이션을 구성합니다(contextClass context-param 및 init-param 사용에 유의하세요).

<web-app>
	<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
		instead of the default XmlWebApplicationContext -->
	<context-param>
		<param-name>contextClass</param-name>
		<param-value>
			org.springframework.web.context.support.AnnotationConfigWebApplicationContext
		</param-value>
	</context-param>

	<!-- Configuration locations must consist of one or more comma- or space-delimited
		fully-qualified @Configuration classes. Fully-qualified packages may also be
		specified for component-scanning -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>com.acme.AppConfig</param-value>
	</context-param>

	<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Declare a Spring MVC DispatcherServlet as usual -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
			instead of the default XmlWebApplicationContext -->
		<init-param>
			<param-name>contextClass</param-name>
			<param-value>
				org.springframework.web.context.support.AnnotationConfigWebApplicationContext
			</param-value>
		</init-param>
		<!-- Again, config locations must consist of one or more comma- or space-delimited
			and fully-qualified @Configuration classes -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>com.acme.web.MvcConfig</param-value>
		</init-param>
	</servlet>

	<!-- map all requests for /app/* to the dispatcher servlet -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/app/*</url-pattern>
	</servlet-mapping>
</web-app>

 

프로그래밍적 사용 사례의 경우 GenericWebApplicationContext를 AnnotationConfigWebApplicationContext의 대안으로 사용할 수 있습니다. 자세한 내용은 GenericWebApplicationContext javadoc을 참조하세요.