앞서 포스팅한 글에서 IoC와 DI에 대해 다루었다.
스프링이 객체를 생성하고 관리하는 제어권을 개발자한테서 가져가면서 IoC가 일어난다고 언급했다.
그렇다면 스프링은 어떻게 객체를 생성하고 관리하는 것이며, 개발자는 이걸 어떻게 사용할까?
아무리 스프링이 객체를 알아서 생성한다고 해도 개발자가 아무것도 하지 않았는데 혼자 그냥 생성할 수는 없다.
개발자는 스프링한테 '어떤 클래스'에서 객체를 생성해달라고 말을 해야 한다.
그리고 그렇게 말하는 수단으로 보통 '@Component'을 사용한다.
import org.springframework.stereotype.Component;
@Component
public class House {
private String name;
public House() {
name = "B house";
System.out.println("Created House Bean");
}
public String getName() {
return name;
}
}
이런 식으로 클래스 위에 @Component를 붙여주면, 해당 클래스의 인스턴스가 스프링 빈으로 등록된다.
여기에서는 House 클래스의 인스턴스가 스프링 빈으로 등록돼서 스프링 컨테이너에 저장된다.
아쉽게도 그렇지 않다.
스프링이 맨 처음 실행되면 어떤 클래스에 @Component가 붙어있는지 찾는 과정을 거쳐야 한다.
그렇게 @Component가 붙어있는 클래스를 찾아야, 해당 클래스에서 생성된 객체를 스프링 빈에 등록할 수 있다.
그리고 이렇게 클래스를 찾는 과정은 @ComponentScan을 통해서 진행한다.
@ComponentScan은 아래와 같이 최상위 인터페이스인 SpringBootApplication의 위에 등록되어 있다.
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
스프링 컨테이너에 저장된 스프링 빈을 사용하기 위해서는 DI를 해야하는데, 이것을 위해서 @Autowired를 사용한다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Person {
House house;
@Autowired
public Person (House house){
this.house = house;
System.out.println("buy " + house.getName());
}
}
이렇게 메서드 위에 @Autowired를 붙이면 메서드의 인자로 개발자가 넘겨주지 않아도, 스프링이 스프링 컨테이너에 있는 빈 중에 타입이 맞는 것을 알아서 넘겨준다.
즉, 이렇게 스프링 빈을 가져다 쓸 수 있는 것이다.