Goal
- @SpringBootApplication 어노테이션에 대해 알아본다
- ApplicationContext에 대해 알아본다
- 어노테이션을 사용하지 않고, 고전적인 방법(ApplicationContext)으로 스프링 빈 설정파일을 만들어본다
@SpringBootApplication
기존의 스프링부트 DemoApplication
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication
- SpringBootConfiguration
- 스프링 부트의 설정을 나타내는 어노테이션
- 스프링의 @Configuration을 대체하며 스프링 부트 전용 어노테이션
- @Configuration이 있으면 스프링은 Java Configure 설정 클래스로 간주하여 Bean으로 등록
- ComponentScan
- 내부스캔
- Configuration, Repository, Service, Controller, RestController
- Component라는 어노테이션이 달린 의존성이 스캔된다.
- EnableAutoConfiguration
- 자동 설정의 핵심 어노테이션
- 클래스 경로에 지정된 내용을 기반으로 설정 자동화를 수행
@SpringBootApplication라는 어노테이션을 사용하면 자동으로 해당 객체들을 빈으로 등록해주기 때문에, 빈 등록을 위한 설정을 할 필요가 없었다. 하지만, 위의 어노테이션을 사용하지 않고서는 어떻게 빈 등록을 할 수 있었을까?
ApplicationContext 란?
- ClassPathXmlApplicationContext - XML
- AnnotationConfigApplicationContext -JAVA
ApplicationContext를 사용해서 빈으로 등록하기
BookService 클래스
public class BookService {
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
- bookService가 bookRepository를 사용한다고 가정
- setter 생성
BookRepository 클래스
public class BookRepository {
}
application.xml - <bean>
<?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">
<bean id="bookService" class="com.example.springapplicationcontext.BookService">
<property name="bookRepository" ref="bookRepository"/>
</bean>
<bean id="bookRepository" class="com.example.springapplicationcontext.BookRepository"></bean>
</beans>
- 스프링 IoC컨테이너는 bean설정 파일이 필요
- bean을 정의하며 id, class 이외 scope, session, request도 설정이 가능
- scope="singleton" 미 설정시, 자동 singleton
- name은 setter에서 가져온다
- ref는 다른 빈을 참조함을 의미하므로, 항상 다른 빈의 id를 세팅해야한다
ApplicationContext를 사용한 DemoApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
String[] beanDefinitionNames = context.getBeanDefinitionNames();
System.out.println(Arrays.toString(beanDefinitionNames));
BookService bookService = (BookService) context.getBean("bookService");
System.out.println(bookService.bookRepository != null);
}
}
결과
[bookService, bookRepository]
true
=> application.xml 설정 파일을 찾아서, IoC 컨테이너에 설정한 bean 객체들을 등록한다.
bookService, bookRepository을 bean으로 등록하였고, bookRepository를 bookService에 의존성을 주입하였으므로
bookService.bookRepository객체는 null이 아니므로, 즉 의존성 주입이 되었음을 확인할 수 있다.
문제
일일이 빈으로 등록하는 일이 굉장히 번거로움
application.xml - <comtext:component-scan>의 등장
<?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.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="com.example.springapplicationcontext"/>
</beans>
- 이 패키지부터 bean을 scanning 해서 등록을 하겠다는 뜻
- @Component
- @Controller
- @Service
- @Repository
BookService 클래스
@Service
public class BookService {
@Autowired
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
- @Service를 사용하여 bean 스캐닝의 대상이 되도록 함 : bean 등록을 위함
- 스프링이 제공하는 @Autowired을 사용하여 의존성 주입
- @Inject를 사용하여 의존성을 주입할 수 있지만 또 다른 의존성을 필요로 함
BookRepository 클래스
@Repository
public class BookRepository {
}
DemoApplication 실행 시 결과
[bookRepository, bookService, demoApplication, org.springframework.context.annotation.internalConfigurationAnnotationProcessor, ...]
true
=> 하위 패키지 모두 등록하기 때문에 등록된 빈 모두 출력
문제
빈 설정 파일을 xml말고 java로 만들 수는 없을까?
Java 설정 파일의 등장
ApplicationConfigutation 설정 파일
@Configuration
public class ApplicationConfiguration {
@Bean
public BookRepository bookRepository(){
return new BookRepository();
}
@Bean
public BookService bookService(){
BookService bookService = new BookService();
bookService.setBookRepository(bookRepository());
return bookService;
}
}
- @Configuration을 사용하여 bean 설정 파일임을 알려주는 어노테이션
- @Bean이라는 자바가 제공하는 configuration을 사용하여 bean으로 등록
- bean의 id : 메서드의 이름 bookRepository()
- type : BookRepository
- 실제 객체 : new BookRepository()
- 세터를 통한 의존성 직접 주입 - 주입시 필요한 인스턴스는 메소드를 호출하거나, 파라미터로 받아 사용 가능
- 유연한 bean 설정이 가능
- 기존의 @Service, @Repository, @Autowired는 제거
DemoApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
System.out.println(Arrays.toString(beanDefinitionNames));
BookService bookService = (BookService) context.getBean("bookService");
System.out.println(bookService.bookRepository != null);
}
}
결과
[bookRepository, bookService, demoApplication, org.springframework.context.annotation.internalConfigurationAnnotationProcessor, ...]
true
=> AnnotationConfigApplicationContext를 사용하여 ApplicationConfig라는 클래스를 넘겨 해당 클래스를 빈 설정으로 사용함
또는
ApplicationConfigutation 자바 설정 파일
@Configuration
public class ApplicationConfiguration {
@Bean
public BookRepository bookRepository(){
return new BookRepository();
}
@Bean
public BookService bookService(){
return new BookService();
}
}
BookService 클래스
public class BookService {
@Autowired
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
빈으로만 등록하고, 의존성 주입은 @Autowired 어노테이션을 사용하여 주입하여도 가능하다.
단, 세터를 사용한 경우에만 가능. 생성자로 주입을 받으면 위의 방법은 불가
문제
일일이 자바 설정 파일에 bean을 등록해줘야 하는 번거로움이 존재
@ComponentScan 어노테이션의 등장
ApplicationConfigutation 설정 파일
@Configuration
@ComponentScan(basePackageClasses = DemoApplication.class)
public class ApplicationConfiguration {
}
- basepackage 와 basepackageClasses가 존재
- basepackage는 문자열을 입력줘야 함
- basepackageClasses는 조금 더 Type safe함
- 해당 클래스가 위치한 곳 부터 컴포넌트 스캐닝을 하라는 뜻
- 즉, 특정 어노테이션에 해당하는 클래스들을 bean으로 등록 @Service, @Repository, @Autowired
우리가 현재 스프링부트에서 사용하는 @SpringBootApplication
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 스프링이 applicationcontext를 자동으로 만듦
- 즉, 이 자체가 bean 설정 파일이다
wow.. 이런 역사가 있었다니,, 놀라워 놀라워!!!!!!!!! 넘 재밌땨
참고
스프링입문 강의 by 백기선
https://www.inflearn.com/course/lecture?courseSlug=spring&unitId=15538 https://www.inflearn.com/course/spring_revised_edition/dashboard
https://www.inflearn.com/course/spring_revised_edition/dashboard
'Spring > about spring' 카테고리의 다른 글
[IoC 컨테이너와 빈] @Component Scan (0) | 2023.07.22 |
---|---|
[IoC 컨테이너와 빈] @Autowired (0) | 2023.07.22 |
[스프링 삼각형] PSA 잘 만든 인터페이스 (0) | 2023.07.17 |
[스프링 삼각형] AOP 관점 지향 프로그래밍 (0) | 2023.07.11 |
[스프링 삼각형] Inversion of Control 제어의 역전 (0) | 2023.07.11 |