class를 만들 때 마다 일일이 넣어주는건 상당히 귀찮은 일입니다.

 

물론 필요할 때도 있겠지만요. 정해진 value 값을 넣어준다거나 할 때, Bean을 직접 만들어 property값들을 제어할 수 있다면 좀 더 디테일하게 다룰 수 있을 것 같습니다.

 

하지만 클래스를 만들 때마다 저렇게 xml에 들어가기에는 상당히 귀찮은 작업이 될 수 있습니다. 

 

이번엔 스프링이 자동으로 Component scan을 하게 만들어 봅시다.

 

아래쪽에 Namespaces를 클릭해주면 이런 체크박스가 나옵니다.

 

여기서 context에 체크를 해주면 이제 component-scan할 패키지를 적어줄 수 있게 됩니다.

 

<?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">

	<context:component-scan base-package="com.duljji"></context:component-scan>
</beans>

 

자 이제 component scan의 패키지도 지정을 해주었으니 우리가 만들어둔 클래스를 Component로 만들어주도록 합시다.

 

방법은 매우 간단합니다. 클래스에 어노테이션만 달아주면 됩니다.

package com.duljji;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Person {
	
	
	public Coke coke;
	
	public Person() {
		
	}
	
	public Person(Coke coke) {
		this.coke = coke;
	}
	
	public void greet() {
		System.out.println("안녕하세요!! Person입니다.");
	}
	
	
	
	
}

 

 

자 다시 greet을 실행시켜 봅니다.

 

와... 자동으로 컴포넌트를 읽어들여 빈으로 만들어준 것을 확인할 수 있습니다.

 

이렇게 Component로 만들어두면 자동으로 의존성을 주입시켜 줄 수도 있는데요 

 

package com.duljji;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Person {
	
	@Autowired
	public Coke coke;
	
	public Person() {
		
	}
	
	public Person(Coke coke) {
		this.coke = coke;
	}
	
	public void greet() {
		System.out.println("안녕하세요!! Person입니다.");
	}
	
	
	
	
}

이렇게 Person클래스에 Coke클래스를 @Autowired를 이용하여 의존성 주입을 해주었습니다.

 

이렇게 컴포넌트로 만들어주면  @Autowired 어노테이션을 이용해 필드주입을 하는 것이 가능해집니다.

 

이전 방식과 마찬가지로 생성자와 Setter를 이용하여 주입도 당연히 가능합니다.

 

<생성자 주입>

package com.duljji;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Person {
	
	public Coke coke;
	
	public Person() {
		
	}
	
	@Autowired
	public Person(Coke coke) {
		this.coke = coke;
	}
	
	public void greet() {
		System.out.println("안녕하세요!! Person입니다.");
	}
	
	
	
	
}

 

Setter주입은 직접 해보시기 바랍니다.

 

 

자, 근데 이런식으로 음료수를 하나만 받는 것은 좀 이상합니다.

 

우리는 이제 음료수를 만들어서 모든 음료수들을 모두 받게 만들겁니다.

 

package com.duljji;

import org.springframework.stereotype.Component;

@Component
public class Coke implements Beverage {

		public void drink() {
			System.out.println("Coke를 마십니다.");
		}
}
package com.duljji;

import org.springframework.stereotype.Component;

@Component
public class Juice implements Beverage {

		public void drink() {
			System.out.println("Juice를 마십니다.");
		}
}

이렇게 Beverage 인터페이스를 만들어 Coke와 Juice 모두를 받을 수 있도록 합니다.

 

package com.duljji;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Person {
	@Autowired
	public Beverage beverage;
	

	public Person() {
		
	}
	
	public Person(Beverage beverage) {
		this.beverage = beverage;
	}
	
	public void greet() {
		System.out.println("안녕하세요!! Person입니다.");
	}
	
	
	
	
}

그런 뒤, 이렇게 Autowired를 하면 어떻게 될까요?

 

당연하지만 에러가 나게 됩니다. 인터페이스를 Autowired해주게 되면, 스프링 컨테이너는 해당 인터페이스를 구현하고 있는 구현체를 넣으려고 하는데, 구현체가 여러개면 어떤걸 넣어주어야 할 지 모르기 때문입니다.

 

하지만 그렇다고, 구현체에 Autowired를 하기에는 너무 결합이 강하게 됩니다.

**

Spring에서 @Autowired를 사용하여 인터페이스를 구현하고 있는 여러 개의 Bean 중 어떤 Bean을 주입해야 할지 알려주어야 합니다. 이를 위해 다음과 같은 방법들이 있습니다:

  1. @Qualifier 어노테이션 사용:
    • @Qualifier 어노테이션은 주입할 Bean을 한정할 수 있는 방법입니다.
    • 해당 어노테이션을 사용하여 주입받을 Bean의 이름이나 식별자를 지정합니다.

Qualifier 를 사용해보도록 합시다.

package com.duljji;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Person {
	@Autowired
	@Qualifier("Coke")
	public Beverage beverage;
	

	public Person() {
		
	}
	
	public Person(Beverage beverage) {
		this.beverage = beverage;
	}
	
	public void greet() {
		System.out.println("안녕하세요!! Person입니다.");
	}
	
	
	
	
}

그런데 이렇게 해주면... Beverage를 나눈 의미가 없어 보입니다.

 

또 한가지 방법은

 

package com.duljji;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

@Component
@Primary
public class Juice implements Beverage {

	public void drink() {
		System.out.println("Juice를 마십니다.");
	}
	
}

 기본적으로 넣어줄 객체를 선정해주는 겁니다. 이렇게 Juice에 Primary 어노테이션을 넣어주면?

 

이렇게 기본적으로 Juice객체가 들어가게 됩니다.

 

아무래도 Autowired를 사용하면 정적인 주입을 하게 되니, 일기 1편에서 썼던것처럼 ApplicationContext 객체를 이용하여 동적으로 직접 주입해주는 것도 필요할 듯 합니다.

+ Recent posts