본문 바로가기
WEB/SPRING

[Spring] 빈(Bean) 🟢

by snow_white 2022. 6. 3.

IoC 컨테이너가 관리하는 객체를 '빈(Bean)'이라고 한다.

 

예를 들어 아래와 같이 new 키워드로 객체를 생성했다고 했을 때 이 인스턴스는 Bean이 아니다.

OwnerController ownerController = new OwnerController();

하지만 같은 ownerController 이지만 아래는 스프링 Bean이라 한다.

applicationContext가 관리하는 객체에서 가져온 것이기 때문이다.

ApplicationContext applicationContext;

@Test
public void getBean(){
	OwnerController bean = applicationContext.getBean(OwnerController.class);
    assertThat(bean).isNotNull();
}

어떻게 스프링 컨테이너 안에다가 이 빈을 만들어줄까?

아래 두 가지 방법으로 Bean을 설정하게 된다.

 

1. Component Scanning

  • @Component
    • @Repository
    • @Service
    • @Controller
    • @Configuration
@Controller
class OwnerController {
	...
}

위의 @Controller 라는 애너테이션이 사실 @Component라는 메타 애노테이션을 사용하는 것이다.

따라서 @Component 애노테이션이라 볼 수 있다.

스프링 IoC 컨테이너가 사용하는 인터페이스들이 있는데 이런 인터페이스들을 라이프 사이클 콜백이라 한다.

@Component가 붙어있는 모든 클래스들을 찾아서 해당 클래스들의 인스턴스를 만들어서 Bean으로 등록하는 과정이 이루어진다. 이 복잡한 과정을 담당하는 애너테이션 프로세서 처리기가 아래와 같이 @SpringBootApplication 애너테이션을 보자.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class PetClinicApplication {

	public static void main(String[] args) {
		SpringApplication.run(PetClinicApplication.class, args);
	}

}

@SpringBootApplication 애너테이션을 들여다보면(위의 PetClinicApplication 클래스에서 마우스를 @SpringBootApplication에 올리고 ctrl+클릭)

@ComponentScan 애너테이션이 있다.

이 애너테이션은 어디서부터 어디까지 Component를 찾아보라고 지시하는 역할을 한다.

@ComponentScan이 붙어있는 위치 즉, @SpringBootApplication 위치에서부터 모든 하위 패키지의 모든 클래스를 탐색하게 된다.

모든 클래스들을 훑어보면서 @Controller 또는 @Component, @Repository 등 애너테이션이 붙어있으면 모두 Bean으로 등록해주는 게 컴포넌트 스캔이라는 기능이다.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
	...
}

그래서 우리가 위의 OwnerController를 직접 Bean으로 등록하지 않더라도 @Controller 애너테이션 덕분에 스프링이 알아서 IoC 컨테이너가 만들어질 때 Bean으로 자동 등록해준다.

예제 프로젝트 PetClinic 에서 Repository(특정 인터페이스)를 상속받은 클래스는 애너테이션 없이도 Bean으로 등록되는데, 스프링 데이터 JPA가 제공해주는 기능에 의해서 자동으로 Bean으로 등록된다.

 

 

2. 직접 XML이나 자바 설정 파일에 빈 등록

 

아래와 같이 자동으로 Bean으로 등록할 수 있게 @Controller 애너테이션을 붙인다.

import org.springframework.stereotype.Controller;

@Controller
public class SampleController {
	...
}

아래는 applicationContext에 SampleController가 Bean으로 등록되어 있는지 확인하는 Test 코드이다.

SampleController를 Component 스캔을 통해서 Bean으로 등록한 것이고, 직접 Bean으로 등록하는 것으로 변경해보자.

@Autowired 애너테이션을 사용하면 IoC 컨테이너에 있는 Bean을 주입받아서 사용할 수 있다. (가장 많이 사용함)

 

@RunWith(SpringRunner.class)
@SPinrgBootTest
public class SampleControllerTest {
	
	@Autowired
	ApplicationContext applicationContext;
	
	@Test
	public void testDI() {
		SampleController bean = applicationContext.getBean(SampleController.class);
		assertThat(bean).isNotNull();
	}

}

 

이와 같이 Bean을 직접 등록할 수 있다.

sampleController() 메서드에서 반환하는 객체 자체가 IoC 컨테이너 안에 Bean으로 등록된다.

@Configuration
public class SampleConfig {
	@Bean
	public SampleController sampleController() {
		return new SampleController();
	}
}

 

그렇기 때문에 더이상 SampleController에 @Controller 애너테이션을 붙일 필요가 없다.

// @Controller
class SampleController {
	...
}

 

 

 

댓글