IOC: Inversion Of Control, 의존관계 주입
IOC Conatainer가 하는 일은 구체적으로 bean을 만들고 bean 사이의 의존성을 엮어주고, bean들을 제공해주는 일을 한다.
-> 클래스 왼쪽에 녹색 콩 표시나면 bean으로 등록됨.
단!!! 의존성 주입은 bean끼리만 가능하다. 즉, spring ioc container안에 있는 객채들 끼리만 의존성 주입을 해준다.
public class BookService{
private BookRepository bookReposiotry;
}
BookService라는 타입의 객체가 사용할 BookRepository라는 객체, 즉 의존관계에 해당하는 의존 객체를 직접 만들어서 사용하는 것이 아니라 어떤 장치 (생성자)를 사용해서 주입을 받아서 사용하는 방법이 IOC이다.
IOC는 스프링이 없어도 저런 장치만 마련이 되어있다면 얼마든지 직접 사용가능.
public void save(){
BookRepository bookRepository = new BookRepository();
BookService bookService = new BookService(bookRepository);
}
우리가 이렇게 하지 않고 IOC라는 스프링이 제공하는 것을 사용하는 이유는 여러 개발자들이 논의해서 만들어낸 Dependency injection방법 등의 노하우가 쌓여있는 방법이기 때문!
bean: 컨테이너 안에 들어있는 객체를 bean이라고 부름
컨테이너라고 부르는 이유는 그 안에 IOC 기능을 제공하는 컨테이너, 뭔가 (bean)를 담고 있기 때문에 컨테이너라고 부르고, bean들이 들어있기 때문에 이 bean들을 가져와서 사용할 수 있다.
스프링 초기에는 xml로 설정하는게 대세였지만, 개발자의 의견으로 어노테이션 기반의 dependency injection을 주입하기 시작.
그럼 어떻게 spring container안에 이 bean을 만들어주느냐, 어떻게 특정한 인스턴스를 bean으로 만들수 있도록하느냐?
2가지 방법이 있다
- component scanning
- 직접 bean으로 등록
왜 bean으로 설정하는가?
1. 의존성을 주입받으려면 bean으로 들어가져 있어야 받을 수 있다.
bean으로 등록되면 장점은?
1). bean의 스코프 때문이기도 함.
- 스프링 IOC 컨테이너에 등록되는 bean들은 기본적으로 single tones scope으로 등록됨.
- 싱글톤: 하나만 만들어서 사용
- 프로토타입: 매번 다른 객체를 사용
- bean으로 등록할 떄 아무런 어노테이션 안붙이면 싱글 톤 스코프로 등록됨.
- 성능 최적화에 유리. 특히 데이터베이스와 일하는 repository는 만드는 비용이 비싼데 싱글톤으로 쉽게 사용 가능
2). 라이프사이클 인터페이스를 지원한다.
- 스프링 IOC 컨테이너에 등록된 bean들에 대해서만 국한된 내용
- bean이 만들어질 때 추가적인 작업을 하고 싶다
스프링 IOC container는 bean 설정 파일이 있어야 하는데,
고전적인 bean 설정파일로
xml에
<bean id="bookService" class="~~"/>
<bean id="bookRepository" class="~~"/>
식으로 만들 수 있고, 여기서 bookService가 bookRepository를 주입 받기 위해서는
<bean id="bookService" class="~~">
<property name="bookRepository" ref="bookRepository"/>
</bean>
<bean id="bookRepository" class="~~"/>
식으로 레퍼런스를 bean으로 주입해주면 된다.
name은 setter에서 가져온 것이고, ref는 다른 bean을 참조해온 것이다.
이 방법의 큰 단점은 bean들을 일일히 등록하기 번거롭다
그래서 등장한게 context의 componentScan!!
<context: component-scan base-package="~~"/>
<bean>으로 생성할 필요 없이 저 한 줄이면 ~~의 패키지부터 bean을 스캐닝해서 등록한다는 의미이다.
bean 스캐닝을 할때는 기본적으로 component라는 어노테이션을 사용해서 등록할 수 있다. (Repository 어노테이션도 가능)
bean으로 등록은 저렇게 하면 되고, 의존성을 주입하기 위해서는 Autowired 어노테이션이 필요하다.
이렇게 설정하고 실행하면 이제는 xml을 읽긴 하지만, component scanning이라는 기능을 사용해서 bean들을 이 패키지 이하에서 어노테이션을 스캐닝해서 등록해준다. (spring 2.5부터 가능!)
이외에
bean 설정파일을 xml이 아니라 자바로 만들순 없을까? 해서 나타난게 자바 설정파일!
ApplicationConfig 이거는 자바 설정파일이라는 의미에서 @Configuration이라는 어노테이션을 붙인다.
자바파일에
@Bean
public BookRepository bookRepository(){
return new BookRepository();
}
@Bean
public BookService bookService(){
BookService bookService = new BookService();
bookService.setBookRepository(bookRepository());
return new bookService();
}
이렇게 bean을 등록해도 bean의 id, type, 객체를 알 수 있다.
실행 자바파일에는
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
를 넣어주어 이 클래스를 bean 설정으로 사용한다. (setter를 사용했을 경우임)
만약 자바로 이렇게 일일히 등록하기 싫다면,
@ComponentScan 어노테이션에 @CompoenetScan(basePackageClasses) 또는 basePackages가 있다
basePackage는 뒤에 문자열을 입력해줘야한다,
@ComponentScan(basePackages = "me.whiteship.springapplicationcontext")
basePackageClasses는 application이 위치한 곳부터 컴포넌트 스캐닝을해라 이뜻!
@ComponentScan(basePackageClasses = DemoApplication.class)
@componentscan이 붙은 그 위치에서부터 모든 하위패키지에 있는 모든 클래스를 다 찾아보면서 @controller, 또는 @component라는 어노테이션을 사용한 어노테이션이 몇가지 더있는데, @repository, @service, @controller, @configuration 등등,..직접 정의도 되고, 이런애들 다 찾아서 bean으로 등록해주는게 conponentscan이라는 기능.
사실 applicationContext도 직접 안만들고 우리는 @SpringBootApplication 이 어노테이션만 붙어있다면 여기에 이미 ComponentScan이 붙어있고, Comfiguration도 붙어있어서 이 자체가 bean 설정파일이다.
정리하면
ApplicationContext
- ClassPathXmlApplicationContext(XML)
- AnnotationConfigApplicationContext(java)
'Programming > Java' 카테고리의 다른 글
[Javascript Framework] Property (0) | 2020.12.28 |
---|---|
[Spring Framework] Bean의 Scope (0) | 2020.12.22 |
[Spring Framework] AutoWired (0) | 2020.12.06 |
[Spring Framework] 스프링 소개 (0) | 2020.12.02 |
[petclinic] PSA (0) | 2020.11.28 |
댓글