본문 바로가기
Spring 프레임워크/이론

IoC 로 객체를 호출 하기 (어노테이션 & .xml)

by Hwanii_ 2023. 8. 1.
728x90

TV 인터페이스

 

 

리모컨 인터페이스

 

 

TV 인터페이스를 구현한, SamsungTV 클래스와,  LgTV 클래스가 있고,

 

RemoteControl 인터페이스를 구현한, SamsungRC 클래스와, LgRC 클래스가 있다.

 

 

SamsungTV 는 TV 인터페이스를 구현 했기에, 추상 메서드를 구현 받은 상황 이고,

 

설계상, channelUp과, volumeDown 은, 리모콘을 통해 기능을 수행 할 수 있다.

 

 

 

그래서, 위와 같이, RemoteControl 인터페이스가 멤버로 (멤버변수) 선언 되어 있다.

 

이는, 의존 관계가 발생 했다고 한다.

 

이렇게 의존 관계가 발생 했을 때, 의존 주입을 해야 한다.

 

 

기존에,

의존 주입을 하는 방법으로는,

생성자를 통해 객체를 주입 하거나,

또는

setter을 통해 주입 하는 방법 이였다.

 

생성자를 통해 객체를 주입 하는 방법은 아래와 같다.

 

SamsungTV 클래스 내부의 인자 1개짜리 생성자

 

 

 

applicationContext.xml 파일에서, <bean> 태그를 사용하여 코드를 작성 한다.

 

<bean class = "패키지명.자료형 (클래스명)" id = "참조변수명" /> 이다.

 

이렇게, /> 를 사용해서, 바로 닫아버리면, 기본 생성자를 뜻하게 된다.

 

생성자에 필요한 인자를  주입하는 방법으로는,

 

<bean class = "패키지명.자료형 (클래스명)" id = "참조변수명">

          <constructor-arg ref = "객체명" />

</bean>

 

이다.

 

이때, 생성자에 필요한 인자가 객체가 아니라,

일반 타입이면, ref 대신에 value를 사용 하지만,

이럴 경우는 거의 없을듯 ?

 

근데,

이제 의존관계라서 필요한 객체 인자를 주입 하기 위해서는,

해당 객체가 new 됬어야지 인자로 주입이 가능 하기 때문에 !

 

<bean class = "패키지명.자료형 (클래스명)" id = "참조변수명" />

 

과 같이 <bean> 태그를 작성해서, 의존관계인 객체를 new 해줘야 한다.

 

 

 

setter을 통해 객체를 주입 하는 방법은 아래와 같다.

 

LgTV 클래스 내부에,  프로퍼티 == 멤버변수 == 의존관계에 놓인 아이

 

에 대해 setter을 만들어 놓는다.

 

 

 

속성명이 name의 값이고 그것에 대한 객체 인자값은 ref의 값이다.

 

그리고,

스프링 컨테이너가 프로퍼티명에 해당하는 세터를 자동 호출 한다.

 

호출하니까 ~ ref의 값을 인자로 넣어, set 하게 된다.

 

 

이제 기존에 의존 주입 방법으로 사용되었던, 

생성자를 통한 주입과

setter을 통한  주입이

아닌,

 

@ (어노테이션) 을 사용한 객체 생성 (호출) 방법에 대해 정리 하겠다.

 

 

@Component 

>> new 역할을 해주는 어노테이션 이다.

 

객체를 new 할 때, 참조변수가 필요하다면,

@Component("참조변수명") 으로 작성 하면 된다.

 

 

 

@Autowired

>> 어노테이션이 작성된 곳의 "자료형" 이 메모리에 올라와 있으면,

 DI (의존 주입) 을 해주는 어노테이션 이다.

 

 

remoteControl 참조변수에 해당 자료형의 객체를 set 하는 느낌으로 생각 해보자.

 

 

위의 이미지는 .xml 파일 내부에 작성된 코드 이다.

 

base-package = "패키지명" 은,

@Component 어노테이션이 스캔할 범위를 지정해주는 기능이다.

 

만약에 test06 이라는 패키지로 위와 같이 지정 해주면,

 

test06 패키지 내부에 있는 모든 클래스에서 @Component 어노테이션을 사용 할 수 있다.

 

@Component 어노테이션을 작성했다면, 객체화가 된다는 의미 이다.

 

또한, 

 

특정한 클래스 (자료형) 내부에 존재하는 멤버에 의존 주입이 필요 하다면,

 

이때까지 했던 방식과 동일하게, <bean class = "패키지명.클래스명" id = "참조변수명" />

 

으로, 해당 자료형의 객체를 new  해주면 된다.

 

 

 

[ 주의할점 ]

 

 

근데, 위와 같이 의존 주입을 하기 위해 필요한 객체 2개를 작성했고,

 

 

 

이렇게 삼성티비 클래스에도 있고, 엘지티비 클래스에도 있다고 가정 해보자.

 

이런 경우에는, 아래와 같은 예외가 발생 하게 된다.

 

 

해당 에러는 스프링 프레임워크에서 @Autowired 어노테이션을 사용해서,

의존성을 주입 하려고 할 때,

주입할 객체가 (빈) 유일 하지 않아서 발생 하는 에러 이다.

 

즉, 동일한 타입의 객체가 여러 개 존재 해서,

스프링이 어떤 객체를 주입 해야 하는지 알 수 없는 상황에서 발생 한다.

 

@Autowired 어노테이션은 우선 순위로 자료형을 읽는다.

 

현재, 삼성티비 클래스 에도, 엘지티비 클래스 에도, 

같은 RemoteControl 이라는 인터페이스 타입의 참조변수 remoteControl 이 선언 되어 있다.

 

그러면,  RemoteControl 이라는 인터페이스 타입을 구현한,

 

 

위의 두 클래스 타입을 읽게 되는데,

 

암튼, 똑같은 인터페이스를 구현한 클래스 들 이기 때문에,

 

@Autowired 어노테이션이 인지를 못하게 되는것이다.

 

[ 해결방법 ]

 

1. 해당 타입 또는 해당 타입을 구현한 타입에 객체를 하나만 생성 하기.

 

즉, 

 

 

이런식으로, 동일한 타입의 객체를 생성 하지 않도록 코드를 작성 한다.

 

2. @Qualifier 어노테이션을 사용한다.

 

주입할 객체명을 명시적으로 지정하여, 충돌을 해결 할 수 있다.

 

 

[ @Component 어노테이션, @Autowired 어노테이션  ]

 

1.

@Component 어노테이션은 스프링에서 관리할 객체를 등록 하기 위해 사용.

 

클래스에 @Component 어노테이션을 붙이면,

해당 클래스는 스프링 컨테이너에 객체로 등록 된다.

 

이렇게 @Component 어노테이션을 사용해서, 객체로 등록된 클래스는,

다른 객체와의 의존성 주입을 받을 수 있다.

 

이때, 의존성 주입을 위해 사용 되는 어노테이션이 바로,

@Autowired 어노테이션 이다.

 

2.

@Autowired 어노테이션은 스프링 컨테이너가,

해당 필드,

메서드 파라미터,

생성자 파라미터,

에 자동으로 의존성을 주입하도록 지정하는 어노테이션 이다.

 

@Autowired 어노테이션을 사용하여 객체로 등록된 클래스들 간의,

의존성을 쉽게 주입 받을 수 있다.

 

3.

정리

 

@Component 어노테이션은 클래스를 스프링 객체로 등록하는 역할.

 

@Autowired 어노테이션은 스프링 컨테이너가 자동으로 의존성을

주입 하도록 지정하는 역할.

 

이 두 어노테이션을 함께 사용하면,

스프링 컨테이너에서 객체로 등록된 클래스들 사이의,

의존성을 쉽고 간편하게 관리 할 수 있다.

반응형