1. IoC 컨테이너와 빈
- IoC(Inversion of Control) : DI(Dependency Injection)이라고도 하며, 어떤 객체가 사용하는 의존 객체를 직접 만들어 사용하지 ㅋ않고 주입받아 사용하는 방법을 말함
- Spring IoC 컨테이너 : Beanfactory, ApplicationContext (Beanfactory 인터페이스를 Implements 함) : 어플리케이션 컴포넌트의 중앙 저장소이면서 빈 설정 소스로 부터 빈 정의를 읽고 빈을 구성하여 제공
빈의 역할 | Spring IoC 컨테이너가 관리하는 객체 |
장점 | |
의존성 관리 | 의존하는 관계의 객체간의 인스턴스 생성을 컨트롤함으로 의존성을 효율적으로 관리 |
테스트 용이 | Mock과 같은 가짜 객체를 만들어 Return 값 조작 가능(의존성 주입이 안된 상태로 의존 관계의 코드의 단위 테스트 어려움) |
스코프 | 싱글톤(기본적으로 Spring IoC Container에서 Bean을 생성할 때 싱글톤 디자인 패턴을 이용하여 생성함, 하나의 객체를 재사용하는 구조이므로 효율적이며 성능이 우수함) |
라이프사이클 인터페이스 | @PostConstruct 등의 어노테이션을 이용하여 빈의 생명주기를 관리하고 특정 시점에 원하는 기능을 수행하게 할 수 있음 |
- 빈 생성, 주입 과정(XML 파일을 이용한 빈 관리)
// application.xml
<?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="me.whiteship.springbootapplicationcontext.BookService">
<property name="bookRepository" ref="bookRepository" />
<!-- application.xml을 이용해서 빈을 생성하고 주입하는 방식은 아주 고전적인 방식이다.
bean = bean 등록, property = bean 주입
name = BookSerivce의 setter, ref = 아래의 bookRepository Bean ID
즉 name에 지정된 setter가 매개변수로 받을수 있는 형이 name에 들어와야 함
bookService Bean은 bookRepository라는 id를 가진 bean으로 부터 bookRepository 의존성 주입받음
이 방법의 단점은 XML에 일일이 등록해줘야 한다는 점이다. 그래서 나온게 context:component-scan 방법임-->
</bean>
<bean id="bookRepository" class="me.whiteship.springbootapplicationcontext.BookRepository"></bean>
</beans>
// BookRepository.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.stereotype.Repository;
public class BookRepository {
}
// BooService.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.beans.factory.annotation.Autowired;
public class BookService {
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository; // BookRepository Bean이 주입됨
}
}
- 빈 생성, 주입 과정(XML 파일에서 Bean을 수동으로 등록하지 않고 자동으로 스캔하여 Bean을 등록)
// application.xml
<?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">
<context:component-scan base-package="me.whiteship.springbootapplicationcontext" />
<!-- component-scan 방식은 패키지 내 @Component 어노테이션이 등록된 클래스를 모두 빈으로 등록함
@Service, @Repository.. 등등의 내부에는 @Component 어노테이션을 쓰고있기때문에
해당 어노테이션으로 등록해도 스캔이 됨 스프링 2.5부터 적용된 기술
세번쨰 방법은 ApplicationConfig.class 파일을 만들어서 @Bean 어노테이션으로 등록하는 방법임-->
</beans>
// BookRepository.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.stereotype.Repository;
@Repository // @CompoentScan, xml의 component-scan 사용시 사용됨
public class BookRepository {
}
// BookService.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.stereotype.Service;
@Service // @CompoentScan, xml의 component-scan 사용시 사용됨
public class BookService {
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
// DemoApplication.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Arrays;
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); //xml로 Bean을 등록할 경우 사용
String[] beanDefinitionNames = context.getBeanDefinitionNames(); // xml, applicationConfig 사용시
System.out.println(Arrays.toString(beanDefinitionNames)); // xml, applicationConfig 사용시
BookService bookService = (BookService) context.getBean("bookService"); // xml, applicationConfig 사용시
System.out.println(bookService.bookRepository); // 주입된 bookRepository 객체!!! // xml, applicationConfig 사용시
}
}
- 빈 생성, 주입 방법 (class 파일을 이용한 빈 관리 : Bean을 직접 등록)
// BookRepository.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.stereotype.Repository;
@Repository // @CompoentScan, xml의 component-scan 사용시 사용됨
public class BookRepository {
}
// BookService.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.stereotype.Service;
@Service // @CompoentScan, xml의 component-scan 사용시 사용됨
public class BookService {
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
// ApplicationConfig.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
public class ApplicationConfig {
@Bean // ApplicationConfig.class를 이용하여 Bean을 "직접" 등록하는 방법
public BookRepository bookRepository(){
return new BookRepository();
}
@Bean
public BookService bookService(){
BookService bookService = new BookService();
bookService.setBookRepository(bookRepository()); // 의존성 주입, 이렇게 하지 않고 @Autowired로 바로 주입가능 (Setter를 사용)
return bookService;
// return new BookService(); // BookService의 BookRepository bookrepository 위에 @Autowired를 사용한다면 이렇게도 의존성 주입 가능
}
}
// DemoApplication.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Arrays;
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class); // ApplicationConfig 파일로 등록할 경우 사용
String[] beanDefinitionNames = context.getBeanDefinitionNames(); // xml, applicationConfig 사용시
System.out.println(Arrays.toString(beanDefinitionNames)); // xml, applicationConfig 사용시
BookService bookService = (BookService) context.getBean("bookService"); // xml, applicationConfig 사용시
System.out.println(bookService.bookRepository); // 주입된 bookRepository 객체!!! // xml, applicationConfig 사용시
}
}
- 빈 생성, 주입 방법 (class 파일을 이용한 빈 관리 : Bean을 자동 등록)
package me.whiteship.springbootapplicationcontext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
@ComponentScan(basePackageClasses = DemoApplication.class) // 메인 클래스부터 관련된 모든 클래스의 @Component 어노테이션을 스캔해라
// 이 방법이 현재 스프링부트에서 사용하고 있는 방법과 가장 가까운 방법이다.
// 스프링부트가 ApplicationConfig 파일조차 자동으로 생성하여 개발자 입장에서는 몰라도되게끔함
// @SpringBootApplication 어노테이션임
public class ApplicationConfig {
}
- 빈 생성, 주입 방법(@SpringBootApplication 어노테이션 사용) : 스프링 부트에 해당
package me.whiteship.springbootapplicationcontext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Arrays;
@SpringBootApplication // 해당 어노테이션만 있다면 @Component 어노테이션이 등록된 클래스를 자동으로 빈으로 등록해줌
// xml이나, ApplicatonConfig를 사용할 필요 없음, SpringBootApplication 내부에 @ComponentScan이 들어가있고 ComponentScan내에 @Configure이 들어가있음
// @SpringBootApplication 자체가 ApplicationConfig 파일과 같다.
public class DemoApplication {
}
}
// BookRepository.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.stereotype.Repository;
@Repository // @CompoentScan, xml의 component-scan 사용시 사용됨
public class BookRepository {
}
// BookService.class
package me.whiteship.springbootapplicationcontext;
import org.springframework.stereotype.Service;
@Service // @CompoentScan, xml의 component-scan 사용시 사용됨
public class BookService {
BookRepository bookRepository;
public void setBookRepository(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
'4. Backend Development > 1. Spring Framework' 카테고리의 다른 글
6. DispatcherServlet (0) | 2020.09.01 |
---|---|
5. Servlet (0) | 2020.09.01 |
4. MacOS Security Management System (0) | 2020.07.21 |
3. Spring Framework 기반 웹 프로젝트 (0) | 2020.06.09 |
1. Spring IoC (Inversion of Control) (0) | 2020.04.29 |
댓글