1.Bean과 Spring container
Bean은 Spring Container가 관리하는 객체이다. Spring container는 Bean의 저장소이며 Bean을 저장, 관리(생성,소멸,연결) 한다.
- BeanFactory : Bean의 기본기능(생성, 연결...)을 정의
- ApplicationContext : BeanFactory를 확장하여 기능을 추가 정의. Spring Container와 유사함.
2.ApplicationContext
XML | Java Config | |
non-Web | GenericXmlApplicationContext | AnnotationConfigApplicationContext |
Web | XmlWebApplicationContext | AnnotationCofigWebApplicationContext |
ApplicationContext는 다양한 구현체를 지원한다. 모든 구현체를 아는 것은 힘들기 때문에 대표적인 4가지 구현체를 살펴본다. 과거에는 XML의 구현체를 많이 사용했지만, 현재는 자바코드를 많이 사용한다.
3.IoC
IoC(Inversion of Control)은 제어의 역적을 의미한다. 즉 제어의 흐름을 전통적인 방식에서 뒤바꾸는 것을 의미한다. 전통적인 방식의 흐름에서는 왼쪽 그림과 같이 사용자 코드 -> Framework코드로 진행된다.(Car객체에서 TurboEngine 객체를 호출) 하지만 제어의 역전(IoC)에서는 Framework코드 -> 사용자 코드로 흐름이 바뀐다. (engine 객체가 SuperEngine을 호출) 이렇듯 IOC는 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리한다.
그렇다면 왜 전통적인 방식이 아닌 역제어 방식을 사용할까? 그 이유는 변하는 코드와 변하지 않는 코드를 분리하기 위함이다. 왼쪽 그림의 코드를 보면 TurboEngine을 제외한 코드들은 모두 잘 변하지 않는 코드들이다. 코드의 번거로움을 줄이기 위해 변하지 않는 코드와 변하는 코드를 분리하기 위해 IoC를 사용해서 오른쪽 그림의 코드와 같이 표현할 수 있다.
오른쪽 그림의 코드를 보면 Framework코드는 모두 변하지 않는 코드로 구성 되어있다. 자주 변하는 코드는 사용자 코드에서 Drive의 매개변수로 설정했다. 그래서 만약 turboDrive에 SoniceEngine로 매개변수를 바꿔야 한다면, 매개변수의 코드만 바꿔주면 된다.
IoC 기법을 활용한 대표적인 예는 테스트 라이브러리인 JUnit을 통해 프로그램을 테스트하는 경우를 이야기 할 수 있다. 테스트의 대상이 되는 프로그램은 테스트 기능을 수행하지 않는다. 대신 테스트 라이브러리인 JUnit에게 제어권을 넘겨 테스트 기능을 수행해 제어한다.
또 다른 예시는 위의에서 살펴본 Spring의 Library들이다. 개발자가 코드를 짤 때 Spring Library를 활용한다. 하지만 우리가 스프링에 있는 다양한 기능을 직접 코딩하진않는다. 외부에 있는 Spring Library에 대한 코드를 활용할 뿐이다.
4.DI(Dependency Injection)
DI(Dependency Injection)는 사용할 객체를 외부에 주입하는 것이다. Spring container에서 타입으로 빈을 검색해서 참조변수에 자동주입을 한다.
Framework코드는 Drive메서드에 SuperEngine을 사용하고자 한다면 새로 객체를 생성하는 등 여러 작업을 해야한다. 하지만 DI를 하게 된다면, 사용자에 있는 SuperEngine을 사용할 수 있다. 이처럼 DI는 객체를 생성하는 코드를 작성 하는것과 같은 번거로운 일을 피할 수 있다.
@Component가 입력된 클래스는 스프링 컨테이너의 스프링 빈으로 등록되고 Component Scan이 스캐닝을 한다. 그 과정에서 스프링 빈으로 등록된 클래스의 생성자에 @Autowired가 등록됐다는 정보를 확인하면 스프링 컨테이너에 등록된 스프링 빈을 자동 주입해준다.
4-1. 자동주입 @Autowired
앞서 살펴본 주입 방식은 수동 주입이다. 자동 주입은 @Autowired 애너테이션을 저장소에 있는 Bean을 주입한다. 붙여 사용할 수 있다. @Autowired는 인스턴스 변수(iv), setter, 참조형 매개변수를 가진 생성자, 메서드에 적용할 수 있다. 생성자에 @Autowired를 가장 많이 사용한다.
@Autowired 연결 흐름
@Component가 입력된 클래스(MemberServiceImpl)는 스프링 컨테이너의 스프링 빈으로 등록된다. 하지만 스프링 컨테이너에 등록되어도 의존관계는 등록되지 않는다. 그래서 의존대상에 @Autowired를 사용한다. Component Scan은 스캐닝을 하는 과정에서 스프링 빈으로 등록된 클래스의 생성자에 @Autowired가 등록됐다는 정보를 확인하면, 스프링 컨테이너에 등록된 스프링 빈(MemberReponsitory)을 자동 주입해준다.
- 인스턴스 변수(iv)
- 참조형 매개변수를 가진 생성자(가장 추천)
- 메서드
※주의사항
1.검색된 Bean이 n개이면, n개의 Bean중에 참조변수와 이름이 일치하는 것을 주입한다.
2.주입 대상이 변수일 때, 검색된 빈이 1개 아니면 예외 발생
3.주입 대상이 배열일 때, 검색된 빈이 n개라도 예외 발생하지않음.
4.@Autowired(required=false)일 때, 주입할 빈을 못찾아도 예외가 발생하지 않는다.
5.@Resource
@Autowired는 Spring Container에서 Type으로 검색해서 자동주입을 한다. 반면 @Resource는 Name으로 Bean을 검색해서 자동 주입한다. 만약 Spring Container에 Bean의 Name이 없으면 예외가 발생한다. @Resource는 Name의 Default값으로 해당 Bean의 Name으로 한다.
6.@Component
<component-scan>로 @Component가 클래스를 자동 검색해서 빈으로 등록한다. @Component는 @Controller, @Service, @Repository, @ContollerAdvice의 메타 애너테이션이다.
출처:스프링의 정석 : 남궁성과 끝까지 간다(패스트 캠퍼스 강좌)
'Spring > Spring DI와 AOP' 카테고리의 다른 글
[Spring DI와 AOP]@Transactional (0) | 2022.07.30 |
---|---|
[Spring DI와 AOP] Transaction, Commit, Rollback (0) | 2022.03.14 |
[Spring DI와 AOP] DAO (0) | 2022.03.12 |
[Spring AOP] AOP의 개념과 사용 (0) | 2022.03.07 |