Java 기반 클라우드 융합 개발자 과정 - KH 정보교육원/9월

22.09.08 - [ Spring ] @Component , @Autowired , injection , IoC 와 DI

giggs 2022. 9. 15. 10:36

 

 

-- INDEX --

 

 

 

1. @Component
사용 이유
2. @Component 3. @Autowired 4. injectrion 5. IoC 와 DI
context 바구니에
가지고있어야할
객체를 알려준다.
@Controller
@Service
@Repository
spring에게
객체를 채워달라고
알려준다.
생성자 인젝션
세터 인젝션
필드 인젝션
제어의 역전과
객체 채워주기

 

 

 


 

 

 

1. @Component 탄생 과정 살펴보기

 

 

 

 

1-1 : home() 메서드 Controller - Service - Dao 에서 각각 구현하기

 

 


 

 

 

1-2 : C - S - D  ㅡ 각 부분에서 수정할 부분 수정하기

 

 

#1. Controller에서 수정할 부분 수정하기

  • 메서드 안에서 new HomeService() 로 객체 만들어주는 부분 안 좋다.
  • 메서드 위쪽에 필드로 만들어주기.
  • 이것뿐만 아니라 – HomeService() 객체가 모든 작업에 필요하다.
  • = 즉, 컨트롤러 태어날 때 HomeService객체 필요하다.
  • = 생성자로 받게 해 주자

 

 

 

 


 

 

#2. Service에서 작업

  • > new HomeDao 만드는 부분 메서드 밖으로 빼기
  • > 메서드 밖으로 빼놔도 문제가 있다. - 구체적인 타입을 적어주어야 하니까
  • > HomeService 레이어에 추가해 줄 모든 메서드들은 작업을 하려면
  • 무조건 HomeDao객체가 필요하다.
  • 생성자에 넣어주자

 

 

 

 

 


 

 

#3. dao 쪽도 작업해주기

 

 

 

 

 

 


 

 

 

1-3 : 기본 생성자 추가해서 서버 실행해보기

 

 

 

 


 

 

우리는 new HomeController 한적 없는데 태어난 이유는?

 

- 어노테이션 때문에 생성자가 호출되고 있다

어떤 객체가 만들어지고 있다.

 

 

 

 

 

 


 

 

 

1-4 : @Component로 서비스 객체와 dao객체 태어나게 해 주기

 

 

 

기본 생성자로 태어난 HomeController

[ HomeService ] 객체를 가지고 태어나지 못해서 에러가 난다.

 

해결방법은?

 

Service와 Dao쪽에

 

@Component 와 기본생성자 추가

 

 

 

 



 

 

 

 

우리는 생성자를 한 번도 호출한 적이 없는데 애들이 다 태어났다!

서버 실행하는 작업밖에 안 했는데 애들이 다 태어났다.

아직 요청을 보낸 게 아무것도 없는데 애들이 다 태어났다.

 

모두 기본 생성자를 통해서 태어났다.

 

가능한 이유는??

 

@Component 라는 어노테이션 때문에 !!

 

 

 

 

 


 

 

 

 

 

2. @Component  { @Controller , @Service , @Repository }

 

  • 톰캣을 실행한 것일 뿐인데 - spring이 자동으로
  • 컨트롤러 객체 / 서비스 객체 / dao 객체 만들어 놓은 상태
  • spring이 객체를 자동으로 만들어주는 기준은?
  • @Component라는 어노테이션 달려있으면 - 인식해서 객체를 만들어주는구나 체크

 

 


 

 

2-1 : @Controller @Service @Repository 사용하는 이유

  • @Component와 마찬가지로 spring의 context 바구니 안에 객체를 만들어주어야겠다 하는 것이다.
  • 다른 점은 이름이 다른 것이다. 
  • 마치 우리가 <div>대신 <header><nav> 같은 시멘틱 태그 사용했듯이
  • 유지보수 측면에서 유리하기 위해서 사용

 

 

 

 

 

사실 @Component 는 잘 안 쓴다. - 어떤 건지 모를 때, 역할 애매할 때 쓰는 것이다.

 

 


 

 

@Component -> @Service 로 수정!

 

 


 

 

@Component -> @Repository 로 수정!

 

 

 

 

 

 

 

 


 

 

 

 

 

3. @Autowired

  • 우리가 home()를 실행하는데 필요한 C –S- D객체 다 만들어진 상태
  • spring은 이미 생성되어서 context(바구니)에 가지고 있는 객체를 가지고 –
  • 들어온 요청에 필요한 애들 뽑아서 - 연결 연결해서 요청을 처리한다.

 

 

 

 

 

 

 

#현재 상태로 메서드를 실행한다면?

  •  컨트롤러 객체에 서비스 객체가 없어서 에러 난다 – nullpoint Exception 

 

 

#객체 만들어놓으면 스프링이 태어날 때 필요한 거 자동으로 넣어준다 그랬는데 왜 안 되냐??

  • 기본 생성자로 태어난 애들이라 – 태어날 때 필요한 것들을 가지고 태어나지 못한다.

 

 

# 해결 방법 

  • 컨트롤러가 만들어질 때 기본 생성자가 아니라 파라미터가 있는 생성자로 태어나게 해 주어야 된다
  • spring이 파라미터 있는 생성자로 객체를 만들어주었으면 좋겠다 생각했다.

 

 


 

 

3-1 : 기본 생성자 지우고 테스트

 

 

 

  • 이제 기본 생성자도 없으니 – 어쩔 수 없이 파라미터 있는 생성자로 만들어주겠지?
  • 컨트롤러가 태어나게 해 주기 위해 – 서비스 객체를 넣어서 만들어주겠지?
  • 안된다. ㅡ 기본 생성자 없다고 에러 발생한다.
  • spring 은  기본생성자 아니고도 만들어주는데
  • 저 HomeService객체를 내가 채워야 하는 게 맞는 건가? 채워도 되는 건가? 몰라서 안된다.
  • spring에게 채워달라고 알려주어야 한다
  • 방법은? ㅡ @Autowired

 

 


 

 

3-2 : @Autowired

 

 

 

@Autowired로 spring에게 채워달라고 알려주고 나니

 

기본 생성자가 아닌 파라미터 받는 생성자로 컨트롤러 태어난 것 확인!

 

 


 

 

서비스 객체도 기본 생성자로 태어나는 것이 아닌 

파라미터 가진 생성자로 태어나게 해주어야 한다

태어날 때 dao객체를 가지고 태어나게 해주어야 한다..

 

 

 

 

 

dao에서는 작업할 거 없다. ( 기본 생성자로 태어나도 괜찮다 )

 

 

 

 

 

 

 


 

 

 

 

 

4. injection의 3가지 방법

  • Autowired를 통해 객체를 넣는 것 = injection (주입)

 

 

4-1 : @Autowired - infection의 3가지 방법

  • 생성자 인젝션 -- C
  • 세터 인젝션 -- S
  • 필드 인젝션 -- F

 

 

 

 

 

 

 

# 생성자 인젝션을 가장 권장한다.

  • 스프링의 권장사항
  • 생성자 인젝션 사용 시 - final키워드 사용가능( 변수가 선언되는 시점부터 값을 가지고있어야하므로 )

 

 

# 필드 인젝션, 세터 인젝션 사용시

  • 좀 더 편하게 사용 가능하다는 장점이 있지만
  • 객체의 불변성 깨진다. , 순환 의존성
  • 실행이 되는 시점에서야 문제점을 발견할 수 있다.
  • 순환 참조라는 문제 사항 생길 가능성이 있다.

 

 

 

 

장단점보다는 뚜렷한 권장사항이 있다.

객체를 만들 때 어떻게 만드는 게 좋은 방법이었나를 생각해보면 똑같다.

 

인젝션이라는게 결국엔 어떤 객체를 만들어서 다른 객체를 만들어 주는 것

, 객체를 만드는 것이다.

 

 

 

 


 

 

 

 

4-2 : 사용법 살펴보기

  • #1. 컨트롤러 인젝션은 위에서 사용해보았다.
  • 필드 인젝션과 세터 인젝션 사용해보기
  • 굳이 생성자를 통해서 @Autowired 해주지 않아도 괜찮다.
  • 그럼, 기본 생성자로 태어난 객체에 – 필요한 객체를 어떻게 채워줄까? - 뒤늦게라도 채워주면 좋을 텐데.

 

 


 

 

#2. 필드 인젝션

  • 해당 클래스 객체가 태어나는데 필요한 필드에 @Autowired
  •  
  • 컨트롤러 객체가 태어나는데 필요한 서비스 객체 -
  • 컨트롤러 클래스에서 작업 - 필드 변수에 @Autowired
  •  
  • 서비스 객체가 태어나는데 필요한 다오 객체 -
  • 서비스 클래스에서 작업 - 필드변수에 @Autowired

 

 

 

 

 

 

이 필드 spring 너가 관리해라 알려주기 - 잘 작동된다.

 

 

 


 

 

 

#3. 세터 인젝션

  • 세터를 만들어주고 거기에 @Autowired

 

 

 

잘 작동한다.

 

 


 

 

spring

이 필드 내가 건드려도 괜찮은 건가??

이 세터 내가 건드려도 괜찮은 건가??

괜찮다고 알려주는 것이 -- @Autowired

 

Spring은 이 객체를 여기에 넣어주어도 되나?

판단하는 기준은 타입

 

 

 

 


 

 

 

5. IoC 와 DI 

 

 

 

스프링의 가장 큰 특징 2가지  IoC , DI

 

 

spring은 클래스 파일 쭉 읽어오면서 

@Component 되어있는 애들 생성자로 만들면서 

그중에 @Autowired있는 애들한테 객체를 넣어준다.

 

 

 

 

 

5-1 : IoC 란?

  • 제어의 역전
  • 개발자가 직접 객체를 생성하고, 메서드를 호출하고 했었는데
  • 이런 거를 이제 spring이 자동으로 알아서 해준다.
  • 매 요청마다 새로운 객체가 생기는 것이 아니라 – 객체가 생성되어있고, 메서드가 호출되도록 동작을 만들어 놓은 것
  • 개발자가 클래스 파일만 잘 만들어놓으면, 프레임워크가 읽어서 파악해서, 객체를 만들어주고, 메서드를 호출해주고 한다.
  • 즉, 개발자가 직접 객체를 생성하고 메서드 호출하는 것이 아닌 – 클래스 파일만 작성해놓으면 프레임워크가 알아서 작업 해주는 것.

 

 

# 이 과정에서 class파일에 있는 객체가 태어나는데 필요한 객체를 넣어주는 것이 - DI

 

 

 

 

 


 

 

5-2 : DI 

  • @Autowired 되어있는 애들한테 – spring이 객체를 넣어준다 – injection 해준다.
  • 이렇게 어떤 객체가 태어나는데 필요한 객체를 넣어주는 작업을
  • Dependency Injection = DI라고 한다.
  • ( 이거 DI좀 해줘 )