이전 글에는 XML Config를 이용하여 Spring Bean 설정 하는 법을 진행하였다. 이 글에서는 Java Config 설정 방식에 대해 알아보려고 하는데, 기본적인 클래스가 필요 하기 때문에 혹시라도 이전 글인 XML Config를 이용한 Spring Bean 설정을 읽지 않았다면 참고하길 바란다.
https://dbjh.tistory.com/21?category=743067
1. Configuration Class를 이용한 Spring Bean 설정
Java Config로 Bean을 설정할때는 XML Config 와 같이 하나의 Class로 여러개의 Bean들을 관리하도록 하는 방식이 있다. Class를 작성하여 Bean 들을 관리하도록 해보자.
ApplicationConfig.java
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ApplicationConfig {
@Bean
public BookRepository bookRepository() {
return new BookRepository();
}
// BookService는 BookRepository를 가지고 있기 때문에 의존성 주입이 필요함
// 1. BookService의 set 메소드를 이용하여 주입하는 방법
@Bean
public BookService bookService() {
BookService bookService = new BookService();
bookService.setBookRepository(bookRepository());
return bookService;
}
// 2. BookService 메소드 파라미터로 다른 Bean 주입하는 방법
@Bean
public BookService bookService(BookRepository bookRepository) {
BookService bookService = new BookService();
bookService.setBookRepository(bookRepository);
return bookService;
}
}
그런 후에 XML 설정을 불러오도록 되어있는 main 메소드 코드를 Java Config 설정을 불러오도록 수정하자.
DemoApplication.java
package com.example.demo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Arrays;
public class DemoApplication {
public static void main(String[] args) {
//ApplicationContext : Bean을 관리하는 IOC 컨테이너
// 삭제
// ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
ApplicationContext context =
new AnnotationConfigApplicationContext(ApplicationConfig.class);
String[] beanNames = context.getBeanDefinitionNames();
// IOC 컨테이너에 등록된 Bean들의 이름 출력
System.out.println(Arrays.toString(beanNames));
// XML Config 파일에 설정해둔 것처럼 BookService에 BookRepository가 주입되었는지 확인
BookService bookService = (BookService) context.getBean("bookService");
// BookService 필드인 bookRepository 객체가 null 인지 확인
System.out.println(bookService.bookRepository != null);
}
}
BookService는 BookRepository를 가지고 있기때문에 의존성 주입이 필요하다. Configuration Class에서 의존성을 주입하는 방법은 위에 ApplicationConfig 파일처럼 두가지 방식이 있는데, 원하는 방법을 사용하면된다. 또는 해당 Class에서 굳이 의존성 주입을 해주지 않고 BookService에 있는 bookRepository 필드에 @Autowired 어노테이션을 명시해줘도 똑같이 동작한다.
Configuration 클래스를 작성하고 BookService와 BookRepository의 어노테이션을 삭제하도록 한다. 이미 Bean으로 등록이 되어 있기때문에 Scan을 위한 어노테이션이 필요없기 때문이다.
BookService.java
package com.example.demo;
public class BookService {
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository){
this.bookRepository = bookRepository;
}
}
BookRepository.java
package com.example.demo;
public class BookRepository {
}
하지만 이 방법은 설정을 Java로 바꾼거 말고 XML에서 일일이 Bean을 등록해 줬던 방식과 다를게 없다. 이 역시도 번거로움이 있다. XML Config와 흐름이 비슷한걸로 보아 결국 어노테이션을 통해 Scanning하여 Bean을 등록하는 방법을 쓰겠지? 라고 예상이 될 것이다. 예상하는대로 Java Config에서도 Compnent Scan을 사용할 수 있다.
2. Component Scan을 이용한 Spring Bean 설정
ApplicationConfig.java
package com.example.demo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
// basePackages 해당 경로부터 스캔
@ComponentScan(basePackages = "com.example.demo")
// basePackageClasses 해당 클래스가 위치한 곳부터 스캔
@ComponentScan(basePackageClasses = DemoApplication.class)
public class ApplicationConfig {
}
@ComponentScan 어노테이션은 위와같이 두가지 방식으로 스캔할 루트 디렉토리를 설정할 수 있는데, basePackages 같은 경우 좋은 IDE가 아니면 직접 입력을 해줘야해서 타이핑에 좀더 안전한 basePackagesClasses 속성을 사용하는게 좋다고 한다.
위와 같이 Scan할 준비가 완료 되었으면 Bean으로 등록해주고 싶은 클래스 용도에 맞게 어노테이션을 명시해주면 된다.
BookService.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookService {
@Autowired
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
BookRepository.java
package com.example.demo;
import org.springframework.stereotype.Repository;
@Repository
public class BookRepository {
}
위와 같이 Java Config를 이용해 ComponentScan을 사용하는 것이 현재 SpringBoot 기반으로 Spring을 사용하고 있는 가장 유사한 방법이다.
하지만, 우리는 ApplicationContext를 직접 생성해서 사용할 일이 거의 없다. Spring이 알아서 다 해주기 때문이다.
SpringBoot에 관련된 설정이긴 하지만, 아래와 같이 코드를 수정해도 문제없이 정상 동작 할것이다.
DemoApplication.java
package com.example.demo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
내부 코드를 보면 알겠지만, 이미 @SpringBootApplication 어노테이션은 @ComponentScan과 @Configuration 어노테이션을 확장하여 사용하기 때문이다.
이것은 SpringBoot 일때의 얘기이고, @ComponentScan과 @Configuration은 Spring의 ApplicationContext에 관련된 것임을 참고하도록 하자.
추가적으로,
XML Config는 ClassPathXmlApplicationContext를 사용하고,
Java Config는 AnnotationConfigApplicationContext을 사용한다.
내용 출처
'Spring' 카테고리의 다른 글
[Spring] @Component와 컴포넌트 스캔 (0) | 2019.12.17 |
---|---|
[Spring] @Autowired 및 Bean 라이프 사이클 (0) | 2019.12.15 |
[Spring] Spring 기본 동작 순서도 (0) | 2019.12.11 |
[Spring] Spring Bean 설정 방법 - XML Config (0) | 2019.12.10 |
[Spring] Spring IOC와 DI (0) | 2019.12.09 |
댓글