어노테이션
어노테이션 설정 추가시, <bean>에 Context관련 namespace와 schema 문서위치 등록필요
- namespace에서 context 체크박스 체크
자동 주소 추가됨
컴포넌트 스캔(component-scan) 설정
- 사용할 객체들 <bean>에 등록하지 않고, 자동으로 생성할때 필요
- <context:component-scan.>엘리먼트 정의
- 설정 추가시, 스프링 컨테이너가 classpath에 있는 클래스 스캔해서, @Component가 설정된 클래스들 자동객체 생성함
src/main/resources/applicationContext.xml
<beans>
<!-- 해당 경로 클래스 스캔해서, @Component설정된 클래스 자동 객체 생성 -->
<context:component-scan base-package="polymorphsim"></context:component-scan>
<bean id="tv" class="polymorphsim.LgTV"></bean>
</beans>
@Component
- 위에 applicationContext에 컴포넌트 스캔 설정했으면, 설정파일에 클래스들을 일일이 <bean>엘리먼트로 등록안해도됨
- 컴포넌트 어노테이션은 클래스 위에 선언 ("변수")
package polymorphsim;
import org.springframework.stereotype.Component;
@Component("tv")
public class LgTV implements TV{
public LgTV() {
System.out.println("===> LgTV 객체 생성");
}
public void powerOn() {
System.out.println("LgTV --전원 켠다.");
}
public void powerOff() {
System.out.println("LgTV --전원 끈다.");
}
public void volumeUp() {
System.out.println("LgTV --소리 올린다.");
}
public void volumeDown() {
System.out.println("LgTV --소리 내린다");
}
}
의존성 주입 어노테이션
스프링에서 의존성 주입을 지원하는 어노테이션
어노테이션 | 설명 |
@Autowired | 변수위에 설정해서, 해당타입 객체 찾아서 자동할당 org.springframework.beans.factory.annotation.Autowired |
@Qulifier | 특정 객체 이름 이용, 의존성 주입시 사용 org.springframework.beans.factory.annotation.Qulifier |
@Inject | @Autowired와 동일기능 제공 javax.annotation.Resource |
@Resource | @Autowired + @Qualifier 기능 결합 javax.inject.Inject |
@Autowired
- 생성자, 메소드, 멤버변수 위에 모두 사용가능 (대부분은 멤버변수위에 선언)|
- 변수의 타입을 기준으로 객체를 검색하여 의존성 주입을 처리
- 스프링 컨테이너가 멤버변수 위에있는 어노테이션 확인하는 순간 변수타입 체크
> 그 타입의 객체가 메모리 존재여부 확인 > 객체를 변수에 주입
- @Autowired가 붙은 객체가 메모리에 없으면, 컨테이너는 NoSuchBeanDefinitionException 발생시킴
(=해당 어노테이션 대상 객체가 메모리에 존재하지 않음)
** 의존성 관계에 있는경우, 관련있는 객체가 메모리에 없는경우 에러가 발생함 (위 이미지처럼)
관련있는 객체를 메모리에 생성하려면, applicationContext.xml에 아래 두가지 방법중 하나
(1) <bean id="~" class="~"></bean> 의존관계 클래스를 bean을 명시하거나
(2) 의존관계 있는 클래스에 @Component("sony")처럼 어노테이션 설정해주기
> 단 <context:component-scan/>에 해당 패키지명이 명시되어있어야함
(예제는 컨테이너가 SonySpeaker객체를 speaker 변수에 자동 할당해준다고 )
@Qualifier
의존성 주입될 객체의 아이디나 이름을 지정할 수 있음.
NoUniqueBeanDefinitionException ㅣ 의존성 주입대상 되는 Speaker타입 객체가 두개이상일때 문제 발생
SonySpeaker과, AppleSpeaker 객체가 모두 메모리에 생성되어있는 상태라면, 컨테이너는 어떤 객체를 할당할지 스스로 판별할수 없어서 에러발생
이런경우, @Autowired되는 대상이 Speaker타입 객체가 AppleSpeaker, SonySpeaker 두개이고, 둘다 메모리에 생성된경우 발생함
해결하기 위해 @Qulifier어노테이션 사용, @AutoWired밑에 명시
src/main/java/polymorphsim/LgTV
package polymorphsim;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("tv")
public class LgTV implements TV{
@Autowired
@Qualifier("apple")
private Speaker speaker;
public LgTV() {
System.out.println("===> LgTV 객체 생성");
}
public void powerOn() {
System.out.println("LgTV --전원 켠다.");
}
public void powerOff() {
System.out.println("LgTV --전원 끈다.");
}
public void volumeUp() {
speaker.volumeUp();
//System.out.println("LgTV --소리 올린다.");
}
public void volumeDown() {
speaker.volumeDown();
//System.out.println("LgTV --소리 내린다");
}
}
실행결과
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml]
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'tv' with a different definition: replacing [Generic bean: class [polymorphsim.LgTV]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\DEV\workspace_spring\BoardWeb\target\classes\polymorphsim\LgTV.class]] with [Generic bean: class [polymorphsim.LgTV]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [applicationContext.xml]]
INFO : org.springframework.context.support.GenericXmlApplicationContext - Refreshing org.springframework.context.support.GenericXmlApplicationContext@69a10787: startup date [Wed Jan 05 00:52:33 KST 2022]; root of context hierarchy
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
===> AppleSpeaker 객체 생성
===> LgTV 객체 생성
===> SonySpeaker 객체 생성
LgTV --전원 켠다.
AppleSpeaker-- 소리 올린다.
AppleSpeaker-- 소리 내린다.
LgTV --전원 끈다.
INFO : org.springframework.context.support.GenericXmlApplicationContext - Closing org.springframework.context.support.GenericXmlApplicationContext@69a10787: startup date [Wed Jan 05 00:52:33 KST 2022]; root of context hierarchy
@Resource
- 객체의 이름을 이용하여 의존성 주입을 처리
- name 속성을 사용, 스프링 컨테이너가 해당 이름으로 객체 검색해서 의존성 주입 처리
- Resource와 같은 기능의 어노테이션 @Inject 둘다 이름기반 의존성 주입
src/main/java/polymorphsim/LgTV
package polymorphsim;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component("tv")
public class LgTV implements TV{
@Resource(name="apple")
private Speaker speaker;
public LgTV() {
System.out.println("===> LgTV 객체 생성");
}
public void powerOn() {
System.out.println("LgTV --전원 켠다.");
}
public void powerOff() {
System.out.println("LgTV --전원 끈다.");
}
public void volumeUp() {
speaker.volumeUp();
//System.out.println("LgTV --소리 올린다.");
}
public void volumeDown() {
speaker.volumeDown();
//System.out.println("LgTV --소리 내린다");
}
}
>> apple 이름으로 메모리에 생성된 AppleSpeaker객체를 speaker변수에 할당
Spring 의존성 주입
XML설정만 사용 | Annotation 설정만 사용 | |
장점 | java소스 수정하지 않고, xml파일 설정만 변경. 유지보수 편리 | - xml 설정에 대한 부담이 없음 - 의존관계에 대한 정보가 java소스에 있어서 사용하기 편리함 |
단점 | - xml설정에 대한 부담감 있음. <bean>등록을 많이 해야함 - 의존관계 설정이 부담스러움 - java 소스에 의존관계와 메타데이터가 없어서, xml설정을 해석해야만 어떤 객체가 의존성 주입되는지 확인가능 |
- 의존성 주입할 객체의 이름이 자바소스에 명시되어야함. - 소스 수정 없이 의존성 관계를 변경할 수 없음 |
** 결론 : 두개를 적절히 섞어서 쓰기
변경되지 않는 객체는 어노테이션으로 설정하여 사용
변경될 가능성이 있는 객체는 XML설정으로 사용
어노테이션 | 클래스 파일명 | 의미 |
@Service | ~ServiceImpl | 비즈니스 로직 처리 Service 클래스 |
@Repository | ~DAO | DB연동 처리 DAO 클래스 |
@Controller | ~Controller | 사용자 요청 제어 Controller 클래스 |
'IT > SPRING' 카테고리의 다른 글
[Spring Boot] (0) | 2023.06.02 |
---|---|
[Spring] Interceptor (0) | 2023.06.02 |
[SPRING] 의존성 주입 (0) | 2022.01.04 |
[SPRING] 스프링 컨테이너, applicationContext 설정파일 (0) | 2022.01.03 |
[SPRING] 프레임워크 개요 (0) | 2022.01.02 |