# 컴포넌트 스캔과 자동 의존관계 설정
- 화면을 고치려면 먼저 컨트롤러와 뷰 템플릿이 필요하다.
- 그러려면 우선 컨트롤러가 있어야 하는데 컨트롤러가 서비스를 통해서 회원가입과 조회를 할 수 있어야 한다.
- 이러한 관계를 의존관계가 있다고 한다(컨트롤러가 서비스를 의존한다).

---

## 컨트롤러 선언시 발생하는 일
- 스프링은 시작할 때 `스프링 컨테이너`라는 것이 생기는데 `@Controller` 어노테이션이 있으면 해당 객체를 생성해서 `스프링 컨테이너`에 넣어두고 관리한다.
- 이를 두고 `'스프링 컨테이너에서 스프링 빈이 관리된다'` 라고 표현한다.
- 스프링이 관리하게 되면 스프링 컨테이너에 등록되고, 스프링 컨테이너에서 받아서 쓰도록 바꿔야 한다. 불필요하게 인스턴스를 생성할 필요가 없다는 뜻이다.
- 즉, 스프링 컨테이너에 등록하면 된다. 스프링 컨테이너에 등록하면 단 하나만 등록된다.
- 스프링 컨테이너와의 연결 방법은 생성자를 만들고 거기에 `@Autowired` 어노테이션을 선언하면 된다.
- 스프링을 시작하고 컨테이너가 뜰 때 `Controller`가 생성되는데 이때 생성자 호출을 하게된다.
- 그런데 생성자에 `@Autowired`라고 되어있으면 생성자로 주입되는 의존성 객체를 스프링이 스프링 컨테이너에서 가져와서 `Controller`에 연결시켜 준다(`Dependency Injection`), 의존성 주입.

![스프링-컨테이너](https://user-images.githubusercontent.com/68052095/102889452-08514f00-449e-11eb-8317-8b56a7c7f88a.PNG)

---

## @Autowired
- 컨트롤러와 서비스등 컨테이너에 등록된 객체를 가져와서 연결시켜줄 때 사용한다.
- 스프링 컨테이너에서 의존성(생성자 파라미터)을 가져온다.
- 하지만 스프링에서 관리하지 않는 순수한 클래스는 가져오지 못한다.
- 서비스의 경우, `@Service`를 클래스에 선언해주면 스프링이 컨테이너에 서비스를 등록해준다.
- 마찬가지로 리포지토리의 경우, `@Repository`를 구현체에 선언해주면 스프링이 컨테이너에 리포지토리를 등록해준다.

---

## Controller, Service, Repository
- 정형화된 패턴이다.
- `Controller`에서 외부 요청을 받는다.
- `Service`에서 비즈니스 로직을 만든다.
- `Repository`에서 데이터를 저장한다.
- 스프링을 실행할 때 위 세 가지를 모두 컨테이너로 가져온다.

---

## 스프링 빈을 등록하는 2가지 방법
- 컴포넌트 스캔(`@Controller, @Service, @Repository 등의 어노테이션 선언`, `각각의 어노테이션은 @Component를 포함하고 있다.`)과 자동 의존관계 설정(`@Autowired`)
    - 스프링은 `@Component`를 포함하는 어노테이션이 있으면 해당하는 것들은 전부 객체를 생성해서 스프링 컨테이너에 스프링 빈으로 등록한다.
- 자바 코드로 직접 스프링 빈 등록하기

---

## 아무데나 @Component를 선언해도 빈으로 등록되는가?
- 아니다.
- `@SpringBootApplication` 어노테이션이 선언된 패키지부터 시작(포함)해서 하위는 스프링이 다 뒤져서 빈으로 등록한다.
- 하지만 하위 패키지가 위의 패키지와 동일하거나 하위 패키지가 아닌 것들은 스프링 빈으로 컴포넌트 스캔을 하지 않으므로 컨테이너에 등록되지 않는다.

---

## 참고
- 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때 기본으로 싱글톤으로 등록한다(유일하게 하나만 등록해서 공유한다).
- 따라서 같은 스프링 빈이면 모두 같은 인스턴스이다.
- 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.

---