안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
Person
@Component : bean으로 관리할 클래스
@Autowired : 의존 주입
/**
* DI(Dependency Injection 의존주입)
* 1. field 주입
* 2. setter 주입
* 3. 생성자 주입
*
*/
@Component
public class Person {
@Autowired
Pet pet;
public Person() {
System.out.println("Person 객체 생성");
System.out.println(pet);
}
}
Pet interface
public interface Pet {
}
Dog
@Component
public class Dog implements Pet {
public Dog() {
System.out.println("Dog 객체 생성!");
}
}
pet-context.xml
beans는 자동으로 포함되며, context 네임스페이스를 사용하기 위하여 context 체크 후 Finish
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!--
base-package하위의 @Component 어노테이션 클래스를 bean으로 관리
-->
<context:component-scan base-package="com.kh.spring.pet"></context:component-scan>
</beans>
xmlns:context가 생성된 것을 확인할 수 있으며, 이는 context 네임스페이스를 사용할 수 있습니다.
네임스페이스가 여러가지일 때 default namespace는 'beans'이며, default namespace는 <beans:bean>처럼 앞에 네임스페이스를 붙이지 않고, <bean>으로 네임스페이스를 생략하여 사용할 수 있습니다.
다만, default namespace가 아니라면 반드시 앞에 네임스페이스를 붙여줘야 합니다. (context:component-scan태그처럼)
<context:component-scan> 태그의 base-package에서 지정한 패키지 하위에 @Component 어노테이션을 빈으로 관리해줌을 의미합니다.
Pet Main
public class PetMain {
public static void main(String[] args) {
String configLocation = "classpath:pet-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println("=================== spring container 초기화 완료 ===================");
}
}
@콘솔출력값
Dog 객체 생성!
Person 객체 생성!
null
=================== spring container 초기화 완료 ===================
따라서 @Component 어노테이션이 붙은 Dog, Person 객체가 생성된 것을 확인할 수 있으며, 객체 생성 시 Pet에 대한 의존 주입이 안된 것을 확인할 수 있습니다. (null)
필드 주입
Person
getPet() 메소드 추가
@Component
public class Person {
@Autowired
Pet pet;
public Person() {
System.out.println("Person 객체 생성!");
System.out.println(pet);
}
public Pet getPet() {
return pet;
}
}
PetMain
public class PetMain {
public static void main(String[] args) {
String configLocation = "classpath:pet-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println("=================== spring container 초기화 완료 ===================");
Person person = context.getBean(Person.class);
System.out.println(person.getPet()); // com.kh.spring.pet.Dog@1d7acb34
}
}
@콘솔출력값
Dog 객체 생성!
Person 객체 생성!
null
=================== spring container 초기화 완료 ===================
com.kh.spring.pet.Dog@1d7acb34
생성자 생성 시에는 Pet 객체에 대한 의존주입이 이루어지지 않았지만, Pet을 사용할 때가 되니 사용직전에 필드에 직접 주입이 된 것을 확인할 수 있습니다.
생성자 주입
Person
@Component
public class Person {
Pet pet;
public Person() {
System.out.println("Person 객체 생성!");
System.out.println(pet);
}
@Autowired
public Person(Pet pet) {
System.out.println("Person 객체 생성! : " + pet);
this.pet = pet;
}
public Pet getPet() {
return pet;
}
}
PetMain
public class PetMain {
public static void main(String[] args) {
String configLocation = "classpath:pet-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println("=================== spring container 초기화 완료 ===================");
}
}
@콘솔출력값
Dog 객체 생성!
Person 객체 생성! : com.kh.spring.pet.Dog@281e3708
=================== spring container 초기화 완료 ===================
생성자 생성 시 Pet 객체가 의존주입 된 것을 확인할 수 있습니다.
setter 주입
Person
@Component
public class Person {
Pet pet;
public Person() {
System.out.println("Person 객체 생성!");
//System.out.println(pet);
}
public Person(Pet pet) {
System.out.println("Person 객체 생성! : " + pet);
this.pet = pet;
}
@Autowired
public void setPet(Pet pet) {
System.out.println("Person#setPet 호출! : " + pet);
this.pet = pet;
}
public Pet getPet() {
return pet;
}
}
PetMain
public class PetMain {
public static void main(String[] args) {
String configLocation = "classpath:pet-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println("=================== spring container 초기화 완료 ===================");
}
}
@콘솔출력값
Dog 객체 생성!
Person 객체 생성!
Person#setPet 호출! : com.kh.spring.pet.Dog@1068e947
=================== spring container 초기화 완료 ===================
기본생성자가 호출된 후 setPet이 호출된 것을 확인할 수 있으며, 마찬가지로 Pet 객체가 주입 된 것을 확인할 수 있습니다.
@Qualifier : 사용할 의존 객체를 선택하여 주입해줌
- 해당 타입의 빈이 2개 이상이라면 오류 발생 → 이름(bean id)으로 지정 가능
- 필드주입/setter주입에만 사용 가능
Cat 클래스 추가
@Component
public class Cat implements Pet {
public Cat() {
System.out.println("Cat 객체 생성!");
}
}
Person
@Component
public class Person {
Pet pet;
public Person() {
System.out.println("Person 객체 생성!");
//System.out.println(pet);
}
public Person(Pet pet) {
System.out.println("Person 객체 생성! : " + pet);
this.pet = pet;
}
@Autowired
public void setPet(Pet pet) {
System.out.println("Person#setPet 호출! : " + pet);
this.pet = pet;
}
public Pet getPet() {
return pet;
}
}
@콘솔출력값
경고: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person': Unsatisfied dependency expressed through method 'setPet' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.kh.spring.pet.Pet' available: expected single matching bean but found 2: cat,dog
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person': Unsatisfied dependency expressed through method 'setPet' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.kh.spring.pet.Pet' available: expected single matching bean but found 2: cat,dog
Cat 클래스를 추가하고, Cat 클래스 또한 bean으로 관리하도록 하였습니다.
하지만 이렇게 된다면, Pet은 Dog, Cat 빈을 가지고 있게 되고 이 때 실행하게 된다면 오류가 발생하게 됩니다.
이런 경우, 어떤 타입의 빈을 주입받을 것인지에 대해 지정해줄 수 있으며, 이 때 @Qualifier 어노테이션을 사용하게 됩니다.
Person
@Component
public class Person {
Pet pet;
public Person() {
System.out.println("Person 객체 생성!");
//System.out.println(pet);
}
public Person(Pet pet) {
System.out.println("Person 객체 생성! : " + pet);
this.pet = pet;
}
/**
*
* @Autowired는 해당 타입의 빈을 찾아서 의존주입
* - 해당 타입의 빈이 2개 이상이라면 오류!
* - 이 때 @Qualifier를 통해 이름(bean id)으로 지정 가능
* - @Qualifier는 필드주입/setter주입에만 사용가능
*
*/
@Qualifier("dog")
@Autowired
public void setPet(Pet pet) {
System.out.println("Person#setPet 호출! : " + pet);
this.pet = pet;
}
public Pet getPet() {
return pet;
}
}
bean id는 클래스명을 소문자로 시작되는 것으로 변환하여 부여!
PetMain
public class PetMain {
public static void main(String[] args) {
String configLocation = "classpath:pet-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println("=================== spring container 초기화 완료 ===================");
}
}
@콘솔출력값
Cat 객체 생성!
Dog 객체 생성!
Person 객체 생성!
Person#setPet 호출! : com.kh.spring.pet.Dog@382db087
=================== spring container 초기화 완료 ===================
@Qualifier("dog")로 Pet 타입으로 처리될 수 있는 bean을 찾되, 이름이 'dog'인 bean을 찾아달라!는 의미로 이번엔 오류없이 Dog 객체가 의존주입된 것을 확인할 수 있습니다.
'Java > Spring' 카테고리의 다른 글
Spring) 페이지 나누기 - param변수, root-context/servlet-context/web.xml 설정 (0) | 2022.08.17 |
---|---|
Spring) Legacy Project 생성 - 버전 최신화하기 (0) | 2022.08.16 |
Spring) Java Annotation을 통한 context 작성 - IoC, DI 특징 파악하기 (0) | 2022.08.12 |
Spring) xml을 통한 context 작성 - DI 특징 파악하기 (0) | 2022.08.12 |
Spring) xml을 통한 context 작성 - IoC 지원 특징 파악하기 (bean 생성) (0) | 2022.08.12 |