[Spring] 자바 코드 기반 설정
자바 코드 기반 설정
Spring JavaConfig 프로젝트는 XML이 아닌 자바 코드를 이용해서 컨테이너를 설정할 수 있는 기능을 제공하는 프로젝트로서, 이를 사용하면 XML이 아닌 자바 코드를 이용해서 생성할 빈 객체와
각 빈 간의 연관 등을 처리하게 된다.
1. @Configuration 어노테이션과 @Bean 어노테이션을 이용한 코드 기반 설정
org.springframework.context.annoatation 패키지의 @Configuration 어노테이션과 @Bean 어노테이션을 이용해서 스프링 컨테이너에 새로운 빈 객체를 제공할 수 있다.
다음은 자바 코드를 이용해서 새로운 빈 객체를 스프링 컨테이너에 제공하는 클래스의 예를 보여주고 있다.
import org.springframework.context.annoatation.Bean;
import org.springframework.context.annoatation.Configuration;
@Configuration
public class SpringConfig{
}
@Bean
public AlarmDevice alarmDevice(){// alarmDevice()를 빈의 식별값으로 사용
return new SmsAlarmDevice();
}
}
@Bean 어노테이션은 새로운 빈 객체를 제공할 때 사용되며, @Bean이 적용된 메서드의 이름을 빈의 식별값으로 사용한다. 따라서 위 코드는 다음의 스프링 XML 설정과 동일한 빈을 정의한다.
<bean id="alarmDevice" class="mad.spring.ch4.homecontrol.SmsAlarmDevice"/>
메서드의 이름이 아닌 다른 이름을 빈 객체의 이름으로 사용하고 싶다면 @Bean 어노테이션의 name 속성을 사용하면 된다.
@Bean(name="smsAlarmDevice")//alarmDevice이 아닌 smsAlarmDevice을 사용하고 싶은 경우
public AlarmDevice alarmDevice(){
return new SmsAlarmDevice();
}
(1) @Bean 객체 간의 의존 설정
의존 설정은 매우 간단하다. 다음과 같이 의존할 빈 객체에 대한 메서드를 호출하는 것으로 의존관계를 설정할 수 있다.
@Configuration
public class SpringConfig{
@Bean
public Camera camera1(){
return new camera();
}
@Bean
public infraredRaySensor windowSensor(){
return new infraredRaySensor("창 센서");
}
@Bean
public Viewer viewer(){
MonitorViewer viewer = new MonitorViewer();
viewer.setDisplayStrategy(displayStrategy());
return viewer;
}
@Bean
public DisplayStrategy displayStrategy(){
return new DefaultDisplayStrategy();
}
@Bean
public HomeController homeController(){
HomeContoller homeController = new HomeController();
List<infraredRaySensor> sensors = new ArrayList<infraredRaySensor>();
sensors.add(windowSensor());
sensors.add(doorSensor());
homeController.setSensors(sensors);
...
homeController.setCamera1(camera1());
homeController.setDisplayStrategy(displayStrategy());
return homeController;
}
}
위 코드에서 각 빈 객체들은 의존할 빈에 해당하는 메서드를 호출함으로써 의존 관계를 설정하고 있다.
여기서 눈여겨 볼 부분은 displayStrategy() 메서드가 viewer() 메서드와 homeController() 메서드에서 각각 한 번씩 호출된다는 점이다.
즉, displayStrategy() 메서드가 두 번 호출된다. displayStrategy() 메서드는 호출 횟수에 상관없이 매번 동일한 객체를 리턴한다.
스프링은 CGLIB를 이용해서 @Configuration이 적용된 클래스의 프록시 객체를 생성한다. 이 프록시 객체는 @Bean 어노테이션이 적용된 메서드가 호출될 때 생성할 빈 객체의 범위에
따라서 알맞은 객체를 제공한다. 예를 들어, 설정한 빈의 범위가 singleton이면 메서드가 리턴하는 객체는 매번 동일한 객체가 되고, 빈의 범위가 prototype이면 메서드가 메번 새로운 빈 객체를
리턴하게 된다.
(2) @Bean 어노테이션의 autowire 속성을 이용한 연관 자동 설정
<bean id="alarmDevice" class="mad.spring.ch4.homecontrol.SmsAlarmDevice" autowire="byName"/>
@Bean(autowire=autowire.BY_NAME)
Autowire.BY_NAME: 이름을 이용해서 자동 연관을 처리한다.
Autowire.BY_TYPE: 타입을 이용해서 자동 연관을 처리한다.
Autowire.NO: 자동 연관 처리를 하지 않는다.
2. @Configuration 어노테이션 기반 설정 정보 사용
클래스에 @Configuration 어노테이션을 적용한다고 해서 스프링 컨테이너가 해당 클래스로부터 빈 정보를 구할 수 있는 것은 아니다.
@Configuration 어노테이션이 적용된 클래스를 이용해서 스프링 빈을 생성하는 방법 2가지를 살펴보자
(1) AnnotationConfigApplicationContext를 이용한 @Configuration 클래스 사용
@Configuration 어노테이션이 적용된 클래스를 설정 정보로 이용하는 첫 번째 방법은 AnnotationConfigApplicationContext를 이용하는 것이다.
다음과 같이 @Configuration 어노테이션 클래스를 전달해 주기만 하면 된다.
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainConfig {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
HomeController homeControl = context.getBean(:homeController", HomeController.class);
....
}
}
cf.) 한 개 이상의 @Configuration 어노테이션 적용 클래스로부터 ApplicationContext를 생성하고 싶다면 다음과 같이 @Configuration 어노테이션 클래스의 목록을 지정하면 된다.
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class, ArticleRepositoryConfig.class);
cf.) AnnotationConfigApplicationContext클래스는 <context:annotation-config> 태그를 사용했을 때와 마찬가지로 각 빈 클래스에서 사용된 @Autowired 어노테이션과 @Resource 어노테이션 등
앞서 '어노테이션 기반 설정' 절에서 살펴봤던 어노테이션들이 기본을 적용된다.
(2) XML 설정 파일에서 @Configuration 어노테이션 클래스 사용하기
XML 설정 파일에서 @Configuration 클래스를 사용하려면 ConfigurationClassPostProcessor 클래스와 @Configuration 어노테이션이 적용된 클래스를 스프링 설정 파일에 빈 객체로 등록해 주면 된다.
<bean class="org.springframework.context.annotation.ConfigurationClassPostProcessor"/>
<bean class="mad.spring.ch4.config.SpringConfig"/>
ConfigurationClassPostProcessor 클래스는 @Configuration 어노테이션이 적용된 빈 객체에서 @Bean 어노테이션이 적용된 메서드로부터 빈 객체를 가져와 스프링 컨테이너에 등록한다.
@Configuration 어노테이션이 적용된 클래스는 @Component 어노테이션이 적용된 클래스와 마찬가지로 컴포넌트 스캔 대상이다. 따라서, 아래와 같이 컴포넌트 스캔 기능을 이용해서
@Configuration 어노테이션이 적용된 클래스를 자동으로 빈으로 등록할 수 있다.
<?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-3.0.xsd">
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="mad.spring.ch4.config"/>
...
</beans>
(3) @Importresource를 통해 @Configuration 설정 클래스에서 XML 사용하기
@Configuration 클래스에서 XML 설정 정보를 사용할 수도 있다.
@Configuration 클래스에서 XML 설정 정보를 함께 사용하고 싶다면 @ImportResource 어노테이션을 사용하면 된다.
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource({"classpath:/article-repository.xml"})
public class ArticleConfigWithImportResource {
@Autowired
private ArticleRepository articleRepository;
@Bean
public ArticleService articleService() {
return new ArticleServiceImpl(articleRepository);
}
}
cp.) @Import를 이용한 @Configuration 어노테이션 적용 클래스의 조합
@Import 어노테이션을 이용하면 하나의 @Configuration 클래스에서 다수의 @Configuration 클래스를 묶을 수 있다. 아래와 같이 @import 어노테이션에 설정 정보를 가져올 @Configuration 클래스 목록을 지정해주면 된다.
import org.springframework.context.annotaion.Cofiguration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({ArticleServiceConfig.class, ArticleRepositoryConfig.class})
public class ArticleConfigWithImport{
...
}
@Import 어노테이션을 이용할 경우의 장점은 개발자가 모든 @Configuration 클래스 목록을 기억할 필요 없이 @import 어노테이션이 적용된 클래스만 기억하면 손쉽게 설정 정보 추적이 가능하다는 점이다.
출처: https://devbox.tistory.com/entry/Spring-자바-코드-기반-설정?category=574587 [장인개발자를 꿈꾸는 :: 기록하는 공간]
'Spring Framework > Spring Core' 카테고리의 다른 글
[Spring] 모델 생성하기 (0) | 2020.07.01 |
---|---|
[Spring] 뷰 지정 (0) | 2020.07.01 |
[Spring] 컨트롤러 메서드의 파라미터 타입 (0) | 2020.07.01 |
[Spring] HTML 폼과 자바빈 객체 (0) | 2020.07.01 |
[Spring] 어노테이션 기반 설정 (0) | 2020.07.01 |
[Spring] 외부 설정 프로퍼티 (0) | 2020.07.01 |
[Spring] iBatis 2 (0) | 2020.07.01 |
[Spring] iBatis 1 (0) | 2020.06.10 |