spring bean
을 선언하는 여러가지 방법이 있다.
spring bean이란 spring ioc container
에 의해 관리되는 특수한 인스턴스를 의미하는데,
보통은 singleton
이다.
다른 scope
들도 존재한다.
그런데 생각해보니 @Bean
과 @Component
둘다 빈을 등록하는 어노테이션인데,
난 @Component
위주로 사용하고 있었다.
@Bean
을 사용하는 경우는 직접 Configuration을 통해서 bean을 등록하는 경우이다.
그래서 둘의 차이점에 대해서 정리해본다.
둘은 사용하는 용도가 다르다.
@Bean은 개발자가 제어할 수 없는 객체를 spring bean으로 만들때 사용한다.
예를 들어서 외부 라이브러리가 있다.
또 메소드에 어노테이션을 달아서 반환되는 객체가 빈이된다.
일단은 간단하게 이런 configuration이 있다고 하자.
@Configuration
public class ApplicationConfig {
@Bean
public ArrayList<String> arrayList() {
return new ArrayList<String>();
}
}
예를 들어서 이런 경우에는 개발자가 제어하기 어려운 ArrayList
를 bean으로 만드는 경우이다.
별도로 해당 라이브러리의 객체를 반환하는 메소드를 선언하고 위에 @Bean
을 붙여준다.
이름을 지정하고 싶으면 다음과 같이 하자.
@Configuration
public class ApplicationConfig {
@Bean
public ArrayList<String> arrayList() {
return new ArrayList<String>();
}
@Bean(name = "arrayListBean")
public ArrayList<String> arrayListBean() {
return new ArrayList<String>();
}
}
의존성 주입은 다음과 같이 한다.
@Configuration
public class ApplicationConfig {
@Bean
public ArrayList<String> arrayList() {
System.out.println("set bean of arrayList with custom name");
return new ArrayList<String>();
}
@Bean(name = "arrayListBean")
public ArrayList<String> arrayListBean() {
System.out.println("set bean of arrayList");
return new ArrayList<String>();
}
@Bean
public Student student() {
System.out.println("set student bean");
return new Student(arrayListBean());
}
@RequiredArgsConstructor
public class Student {
private final ArrayList<String> arrayList;
}
}
그리고 실제로 개발자가 제어하지 않는 라이브러리의 인스턴스를 Bean으로 만들었는데,
실제로 Singleton bean으로 잘 선언됬는지 체크해보자.
이런 테스트 코드를 작성해보자.
@SpringBootTest
@RunWith(SpringRunner.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ApplicationConfigTest {
@Autowired
ArrayList<String> arrayList;
@Autowired
ApplicationContext applicationContext;
@Test
@Order(1)
public void setArrayList() {
arrayList.add("asdf");
System.out.println("added");
}
@Test
@Order(0)
public void checkApplicationContext() {
ArrayList arrayList = applicationContext.getBean("arrayList", ArrayList.class);
Assert.assertNotNull(arrayList);
}
@Test
@Order(2)
public void printArrayList() {
System.out.println("arrayList = " + arrayList);
}}
대충 실행시켜보면 로그 잘 찍힌다.
그럼 @Component
는 언제 사용하는 걸까 ?
이건 너무 당연하겠지만 개발자가 직접 작성한 클래스를 Spring Bean으로 만들기 위해 사용한다.
샘플로 코드를 작성해보자.
@Configuration
public class ApplicationConfig {
@Component
public class Apple {
private Color color;
@Autowired
public Apple(Color color) {
this.color = color;
System.out.println("Apple bean creation completed");
}
}
@Component
public class Color {
private ColorVar colorVar;
public Color() {
this.colorVar = ColorVar.RED;
System.out.println("Color Bean Creation Completed");
}
}
public enum ColorVar {
RED, GREEN
}
}
이렇게 @Component를 달면 끝 !