일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- sope
- Singtone
- bitmasking
- Algorithm
- 자바
- 전화번호 목록
- 가장먼노드
- 프로그래머스
- 이진검색
- 플로이드워셜
- 카카오인턴
- Java
- Spring
- 쇠막대기 문제
- 스프링프로젝트 시작하기
- Spring이란
- 토비의스프링
- 스프링이란
- 그래프
- BinarySearch
- 플로이드와샬
- @Profile
- 징검다리
- 구현
- 카카오
- 백준
- 알고리즘
- 11723
- 이진탐색
- 스프링
- Today
- Total
육감적 코딩
[Spring] 2. ApplicationContext와 다양한 빈 설정 방법 본문
정리 시작 전 이해를 돕기위한 사전설명
-
프로젝트는 Spring Boot의 web starter만 dependency를 받아 사용.
-
BookService , BookRepository class를 만들어 사용하였습니다.
public class BookService {
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
public class BookRepository {
}
다양한 ApplicationContext 설정방법
-
ClassPathXmlApplicationContext
아주 고전적인 Spring Bean설정방법
일단 resources의 하위 경로에 “application.xml” 파일을 생성
<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 https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="bookService" class="me.jsh.springapplicationcontext.BookService"/>
<bean id="bookRepository"class="me.jsh.springapplicationcontext.BookRepository"/>
</beans>
<bean>의 하위 속성을 간단히 살펴보면
id : bean의 id를 의미합니다. 보편적으로 첫 글자는 소문자를 사용합니다.
class: bean의 타입을 의미합니다.
scope: 해당 예제에는 사용하지않았기 때문에 간략히 설명. 속성으로는
-
prototype : 매번 새롭게 만들어서 사용
-
request : 리퀘스트 마다 새롭게 만들어서 사용
-
session : 세션마다 만들어서 사용
-
singleton : application을 통틀어 한번만 생성 (속성을 지정해주지않으면 기본 값)
package me.jsh.springapplicationcontext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.ApplicationContext;
import java.util.Arrays;
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); // context 파일인 applicaition.xml를 읽어옵니다.
String[] beanDefinitionNames = context.getBeanDefinitionNames(); // 등록된 Bean의 id를 가져옵니다.
System.out.println(Arrays.toString(beanDefinitionNames)); // Bean들의 id를 출력
BookService bookService = (BookService) context.getBean("bookService"); //BookService는 BookRepository를 필드로 가지고있기때문에 제대로 생성되었는지 확인
System.out.println(bookService.bookRepository != null); // bookRepository가 있는지 확인
}
}
여기까지 작성을 한 뒤 실행.
application.xml의 빈들은 정상적으로 읽어와 출력이 되지만,
bookService의 bookRepository는 null 이기 때문에 false를 출력합니다.
why?
당연히 BookRepository가 빈으로 등록되었지만, 이를 BookService의 주입하지않았기때문입니다.
application.xml 를 수정해줍니다.
<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 https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="bookService" class="me.jsh.springapplicationcontext.BookService">
<property name="bookRepository" ref="bookRepository"/>
</bean>
<bean id="bookRepository" class="me.jsh.springapplicationcontext.BookRepository"/>
</beans>
bean으로 생성된 BookRepository를 Bookservice에 DI 해줍니다.
당연히 다시 실행해 보면 true를 반환합니다.
application.xml를 보면 모든 빈을 직접 등록해줘야한다는 아주 큰 단점이있습니다.
그래서 등장한 방식인 context:component-scan 입니다.
<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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="me.jsh.springapplicationcontext"/>
</beans>
= me.jsh.springapplicationcontext 패키지 부터 컴포넌트를 스캐닝 하여 빈을 등록하겠다.라는 뜻을 가지고있습니다.
기본적으로 @Component 어노테이션을 사용하여 빈으로 등록을 할 수 있습니다.
@Component
public class BookService {
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
@Component
public class BookRepository {
}
@Component가 붙은 class 들을 스캔하여 빈으로 등록합니다.
@Component를 확장한 몇가지 어노테이션이 있습니다.
@Service , @Repository 등등
@Service 애노테이션을 타고들어가면 @Component가 붙어있는것을 확인 할 수있습니다.
즉, 기능과 사용처에따라 이 확장된 어노테이션을 사용해도 Component-scan에 해당 클래스들이 걸리게됩니다.
@Service
public class BookService {
@Autowired // 추후에 자세히 설명. Bean을 주입받아 사용한다 정도로 생각
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
@Repository
public class BookRepository {
}
실행을 하면 정상적으로 context파일을 읽어들여 빈이 생성되는것을 확인할 수 있습니다.
하지만 기존의 동작 방식과는 조금 차이가 있습니다.
해당 방법은 component들을 스캔하여 빈들을 생성합니다.
지금까지 ClassPathXmlApplicationContext 를 사용한 context작성을 알아보았습니다. 다음으로 알아볼 방법은
AnnotationConfigApplicationContext 를 사용한 context 작성을 알아보겠습니다.
-
AnnotationConfigApplicationContext
xml파일말고 java로 만들수 없을까?
라고생각하여 등장한게 자바설정파일 입니다.
기존의 애노테이션들을 모두 제거한 뒤,
ApplicationConfig 클래스를 만들어줍니다.
@Configuration 애노테이션을 사용합니다.
@Configuration
public class ApplicationConfig {
@Bean
public BookRepository bookRepository(){
return new BookRepository();
}
@Bean
public BookService bookService(){
BookService bookService = new BookService();
bookService.setBookRepository(bookRepository());
return bookService;
}
}
context를 읽어오는 방식이 바뀌었기 때문에 main을 수정해 줍니다.
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
System.out.println(Arrays.toString(beanDefinitionNames));
BookService bookService = (BookService) context.getBean("bookService");
System.out.println(bookService.bookRepository != null);
}
}
정상적으로 작동하는것을 확인할 수 있습니다.
xml파일을 만들필요도 없기때문에 편리하지만, 아직 이 방식에도 불편한 점이 있습니다.
가장 원시적인 xml로 빈등록을 했던것과 같이 모든 빈들을 직접 등록해주어야합니다.
하지만
사실 component-scan을 통한 방식이 존재합니다.
@ComponentScan 애노테이션을 이용하는 방식입니다.
-ApplicationConfig.class-
@Configuration
@ComponentScan(basePackageClasses = DemoApplication.class)
public class ApplicationConfig {
}
“DemoApplication”클래스의 패키지부터 스캔을 하여 @Component 애노테이션이붙은 (이를 확장한 @Service, @Repository, @Controller 등등) 클래스를 확인하여 빈으로 등록해 줍니다.
이로인해 기존의 ApplicationConfig의 빈을 일일히 등록하는 번거로움을 덜 수 있습니다.
하지만 이런 방식으로 ApplicationContext를 생성하여 사용하는 방법보다 더 간단한 방법이 있습니다.
SpringBoot에서 지원해주는 방식을 사용하는 것입니다.
바로 @SpringBootApplication 애노테이션을 이용하는 방식입니다.
@SpringBootApplication를 타고 올라가보면
@ComponentScan 애노테이션이 붙은 걸 확인할 수 있으며,
@Configuration 애노테이션이 붙은걸 확인할 수 있습니다.
즉, 기존의 ApplicationConfig.class 가 필요없습니다. (삭제해줍니다.)
사실상 @SpringBootApplication이 붙은 이 자체가 ApplicationContext역할을 합니다.
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
}
}
지금까지 xml설정파일을 이용하여 빈을 등록하여 사용하는 방식과
애노테이션을 이용한 자바 설정파일을 이용하여 빈을 등록하여 사용하는 방식에 대해 정리해보았습니다.
또한 Springboot에서 지원해주는 @SpringBootApplication을 통해 빈을 등록하여 사용하는 방법에대해서도 정리해보았습니다.
'정리 > Spring' 카테고리의 다른 글
토비의스프링3.1 [7장] 7.5 DI를 이용해 다양한 구현 방법 적용하기 (0) | 2020.07.29 |
---|---|
[Spring] 3. @Autowired (0) | 2020.07.23 |
[Spring] 1. IoC컨테이너와 빈 (0) | 2020.07.20 |
토비의스프링3.1 [6장] 6.5 스프링 AOP (0) | 2020.07.13 |
토비의스프링3.1 [2장] 테스트 (0) | 2020.06.19 |