# Dependency Injection

### Factory

* 자바에서 객체를 사용할 때 클래스 타입을 지정하지 않고, 팩토리를 사용하여 객체를 생성하는 일종의 패턴이다.
* 이 패턴은 객체 생성을 캡슐화하여 객체 생성 코드를 단순화할 수 있고 중앙집중화 할 수 있다.\\

### @Component

* Spring Bean으로 등록하기 위한 어노테이션이다. 여기서 Spring Bean이란 스프링에서 관리하는 객체로서 스프링 IoC컨테이너가 생성하고 관리한다.
* 이 어노테이션은 spring에서 자주 사용되는 @Service, @Repository, @Controller 등의 어노테이션에도 포함되어 있다.\\

### @Bean

* 이 어노테이션은 개발자가 직접 생성하고 제어하는 Bean을 IoC컨테이너에 등록하는 기능을 한다.
* `@Bean`은 메서드 레벨에서 사용된다. 그리고 해당 메서드가 생성하는 객체를 스프링 IoC컨테이너에 등록한다.
* 주로 외부 라이브러리나 다른 설정 파일에서 Bean 객체를 가져와 등록할 때 사용한다.\\

### @ComponentScan

* Component를 Scan하는 의미로 받아들이면 쉽다. @Component를 이용하여 Bean으로 등록하려는 클래스들을 인식하는 방법이다.
* 스캔 대상 패키지나 클래스를 지정하여 사용할 수 있다.

```
// 패키지를 대상으로 스캔
@ComponentScan(basePackages = "com.example") 
```

\\

### Spring AOP(Aspect Oriented Programming)

* 한국말로 관점지향 프로그래밍이다.
* 비즈니스 로직으로부터 공통적으로 반복되는 기능을 분리해낼 수 있게 해준다.
* 좀 더 자세히 말하자면, 반복적으로 반복되는 코드를 추상화하여 공통 모듈로 만들고, 만들어진 공통모듈을 의도한 코드에 삽입하여 사용하게 한다.
* 이로 인해서, 핵심 비즈니스에 좀 더 집중할 수 있고 응집도 높은 코드를 만들 수 있게 한다.
* AOP의 주된 용도의 예로는 로깅, 보안, 트랜잭션 처리 등이 있다.\\

### Dependency Injection

* 스프링에서 객체 간의 의존성을 주입하는 방식이다.
* DI가 없이 객체를 생성한다면, 한 객체가 의존하는 다른 객체를 의존하게 된다. 하지만 이렇게 되면 한 객체가 다른 객체의 존재와 그에 대한 정보를 알아야 하기 때문에 의존도가 높게 된다. 이로 인해 코드가 변경될 경우 영향도가 커지게 되어 유지보수성이 악화되고 확장성이 떨어지게 된다.
* DI는 객체의 의존관계를 직접 작성하지 않고 외부로부터(Spring으로부터) 주입받도록 한다. 이것을 관리하는 것이 스프링의 컨테이너이다. 컨테이너는 객체의 의존관계를 파악하고 객체 생성 시에 자동으로 주입한다.
* 객체를 주입받는 방법은 생성자 주입방식이 있고, setter 주입 방식이 있다.\\

### 싱글턴 패턴

* 쉽게 말하면 오직 하나의 객체만 생성하도록 강제(또는 보장)하는 패턴이다.
* 싱글턴 패턴은 전역 상태나 리소스 관리를 위한 하나의 객체만 필요한 경우 사용한다고 한다.
* 싱글턴 패턴의 특징은 다음과 같다.
  * 클래스 내부에 유일한 인스턴스가 존재한다.
  * 싱글턴 객체에 접근하기 위한 전역적인 접근점이 제공된다.
  * 싱글턴 객체를 생성하기 위한 방법은 오직 한가지 뿐이다.
* 간략히 싱글턴 객체를 생성하도록 하는 방법을 알아보자면,
  1. 클래스 내부에 유일한 객체를 저장할 변수(static 변수)를 선언한다.
  2. 생성자를 private으로 선언하여 외부에서 객체 생성을 하지 못하도록 막는다.
  3. 싱글턴 객체에 접근할 수 있는 유일한 static 메서드를 제공한다.\\

### IoC(Inversion of Control)

* 해석해보면 제어(Control)의 역전(Inversion)이다.
* 객체생성을 개발자가 하는 것이 아니라 프레임워크(스프링과 같은)가 하도록 위임하는 것이다.
* 그리고 이것을 구현하기 위해 필수적인 기술이 DI(Dependency Injection, 의존성 주입)이다. DI의 주체는 프레임워크인데, 마찬가지 맥락으로 개발자가 객체 간의 의존성을 주입하는 것이 아닌 스프링의 컨테이너가 의존관계를 파악하여 객체 생성 시에 자동으로 주입하는 것을 말한다.
* IoC와 DI를 위해서는 객체의 관계를 미리 정의하는 작업이 필요하다. 스프링부트 이전에는 XML에도 작성했었지만, 이제는 다양한 어노테이션과 자바 코드 등으로 다양하게 작성할 수 있다.
* IoC의 장점은 무엇일까? IoC를 통해서 개발자가 핵심 비즈니스에 더 집중할 수 있다. 매번 객체 간의 의존관계를 설정하는 수고를 덜 수 있기 때문이다. 그리고 또한 유지보수성을 높일 수 있다. 왜냐하면 객체 간의 영향도(결합도)를 낮추기 때문인데, 이것은 스프링이 제공하는 DI방식 덕분이다.\\

### Spring Bean

* 스프링이 관리하는 Bean(객체)를 말한다.
* 좀 더 구체적으로는 스프링 컨테이너(Spring container)에서 관리하는데, 이때 컨테이너가 관리하는 객체를 Spring Bean이라고 한다.
* 스프링 컨테이너는 관리하기로 정의된 객체에 대해서 Bean을 생성 / 초기화 / 소멸 등의 생명주기(Life Cycle)를 관리한다.\\

### BeanFactory

* Bean을 생성하고 관리하는 인터페이스이다. Spring Container의 핵심 기능 중의 하나이다.
* BeanFactory 인터페이스를 구현한 클래스로는 `DefaultListableBeanFactory`, `XmlBeanFactory`, `ApplicationContext` 등이 있다. 이 클래스들은 스프링 컨테이너에서 Bean을 생성하고 관리하는 기능을 구현했다.
