[Spring] 어노테이션(Annotation)을 이용한 스프링 설정
| 어노테이션(Annotation)을 이용한 스프링 설정
스프링에서는 XML 설정을 통해 Bean 객체를 컨테이너 상에서 구현할 수 있지만 Java 파일을 이용해서도 구현할 수 있다.
다음의 XML 설정파일을 Java 설정 파일로 변환하면 다음과 같다.
<?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-3.2.xsd">
<context:annotation-config/>
<bean id="gun" class="com.tutorial.spring.Gun"/> <!-- 생성, 소멸시 실행될 메서드 지정 -->
<bean id="knife" class="com.tutorial.spring.Knife"/>
<bean id="gunPlayer" class="com.tutorial.spring.Player"/>
<bean id="gunPlayer2" class="com.tutorial.spring.Player2"/>
</beans>
@Configuration
public class JavaConfig {
@Bean
public Gun gun() {
return new Gun();
}
@Bean
public Knife knife() {
return new Knife();
}
@Bean
public Player gunPlayer() {
return new Player(gun());
}
@Bean
public Player gunPlayer2() {
return new Player(knife());
}
}
혹은 일일이 @Bean 설정을 하지 않고 @ComponentScan을 통해서 Type-safe한 방법으로 설정하는 방법이 있다.
@Configuration
@ComponentScan(basePackageClasses = SpringTutorialApplication.class)
public class JavaConfig {
}
실행을 하면 다음과 같다.
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
Player gunPlayer = ctx.getBean("gunPlayer", Player.class);
gunPlayer.usePlayerWeapon();
Player gunPlayer2 = ctx.getBean("gunPlayer2", Player.class);
gunPlayer2.usePlayerWeapon();
ctx.close();
}
}
// 결과
12월 01, 2018 10:17:17 오후 org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
정보: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
12월 01, 2018 10:17:17 오후 org.springframework.context.support.AbstractApplicationContext prepareRefresh
정보: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@439f5b3d: startup date [Sat Dec 01 22:17:17 KST 2018]; root of context hierarchy
12월 01, 2018 10:17:17 오후 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
정보: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
(...)
Use Gun
Use Knife
12월 01, 2018 10:17:17 오후 org.springframework.context.support.AbstractApplicationContext doClose
정보: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@439f5b3d: startup date [Sat Dec 01 22:17:17 KST 2018]; root of context hierarchy
12월 01, 2018 10:17:17 오후 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
(...)
| 자바 설정 파일 분리 및 합치기(Java Config File Split and Merge)
자바 설정파일 역시 XML 파일 처럼 여러 개의 설정파일로 분리할 수 있다.
다음 스프링 프로젝트 구조에서 JavaConfig, JavaConfig2 설정 클래스를 AnnotationConfigApplicationContext 를 통해 컨테이너 생성 후 로딩할 수 있다.
JavaConfig.java
@Configuration
public class JavaConfig {
@Bean
public Gun gun() {
return new Gun();
}
@Bean
public Knife knife() {
return new Knife();
}
@Bean
public Player gunPlayer() {
return new Player(gun());
}
@Bean
public Player knifePlayer() {
return new Player(knife());
}
}
JavaConfig2.java
@Configuration
public class JavaConfig2 {
@Bean
public Bow bow() {
return new Bow();
}
@Bean
public Player bowPlayer() {
return new Player(bow());
}
}
위 설정파일을 토대로 AnnotationConfigApplicationContext 객체를 통해 컨테이너를 구성할 수 있다.
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(JavaConfig.class, JavaConfig2.class); // 복수의 설정파일을 가지고 컨테이너를 만들 수 있다
Player gunPlayer = ctx.getBean("gunPlayer", Player.class);
gunPlayer.usePlayerWeapon();
Player knifePlayer = ctx.getBean("knifePlayer", Player.class);
knifePlayer.usePlayerWeapon();
Player bowPlayer = ctx.getBean("bowPlayer", Player.class);
bowPlayer.usePlayerWeapon();
ctx.close();
}
}
// 결과
12월 01, 2018 10:17:17 오후 org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
정보: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
12월 01, 2018 10:17:17 오후 org.springframework.context.support.AbstractApplicationContext prepareRefresh
정보: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@439f5b3d: startup date [Sat Dec 01 22:17:17 KST 2018]; root of context hierarchy
12월 01, 2018 10:17:17 오후 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
정보: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
(...)
Use Gun
Use Knife
Use Bow
12월 01, 2018 10:17:17 오후 org.springframework.context.support.AbstractApplicationContext doClose
정보: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@439f5b3d: startup date [Sat Dec 01 22:17:17 KST 2018]; root of context hierarchy
12월 01, 2018 10:17:17 오후 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
(...)
@Configuration
@Import({JavaConfig.class, JavaConfig2.class})
public class JavaConfigAll {
}
위 JavaConfigAll 클래스만을 토대로 컨테이너를 구성해줘도 JavaConfig, JavaConfig2 클래스들을 토대로 컨테이너 설정을 구성한 것과 같은 효과를 볼 수 있다.
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(JavaConfigAll.class); // 하나만 인자로 넣어도 됨
Player gunPlayer = ctx.getBean("gunPlayer", Player.class);
gunPlayer.usePlayerWeapon();
Player knifePlayer = ctx.getBean("knifePlayer", Player.class);
knifePlayer.usePlayerWeapon();
Player bowPlayer = ctx.getBean("bowPlayer", Player.class);
bowPlayer.usePlayerWeapon();
ctx.close();
}
}
// 결과
12월 01, 2018 10:17:17 오후 org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
정보: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
12월 01, 2018 10:17:17 오후 org.springframework.context.support.AbstractApplicationContext prepareRefresh
정보: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@439f5b3d: startup date [Sat Dec 01 22:17:17 KST 2018]; root of context hierarchy
12월 01, 2018 10:17:17 오후 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
정보: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
(...)
Use Gun
Use Knife
Use Bow
12월 01, 2018 10:17:17 오후 org.springframework.context.support.AbstractApplicationContext doClose
정보: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@439f5b3d: startup date [Sat Dec 01 22:17:17 KST 2018]; root of context hierarchy
12월 01, 2018 10:17:17 오후 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
(...)