[Spring Framework] Spring IoC 컨테이너 사용법 완벽 정리 | 실전 예제로 이해하는 DI
[Spring Framework] Spring IoC 컨테이너 사용법 완벽 정리 | 실전 예제로 이해하는 DI
[Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의 [Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의[Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리 [Spring Framework] Spring Framework란? 개
crushed-taro.tistory.com
1. IoC Container
1. Annotation-based Configuration
1. @ComponentScan이란?
- base package로 설정 된 하위 경로에 특정 어노테이션을 가지고 있는 클래스를 bean으로 등록하는 기능이다.
- @Component 어노테이션이 작성 된 클래스를 인식하여 bean으로 등록한다.
- 특수 목적에 따라 세부 기능을 제공하는 @Controller, @Service, @Repository, @Configuration 등을 사용한다.
어노테이션 | 설명 |
@Component | 객체를 나타내는 일반적인 타입으로<bean> 태그와 동일한 역할 |
@Controller | 프리젠테이션 레이어. 웹 어플리케이션에서 View에서 전달된 웹 요청과 응답을 처리하는 클래스 EX) Controller Class |
@Service | 서비스 레이어, 비즈니스 로직을 가진 클래스 EX) Service Class |
@Repository | 퍼시스턴스(persistence) 레이어, 영속성을 가지는 속성(파일, 데이터베이스)을 가진 클래스 EX) Data Access Object Class |
@Configuration | 빈을 등록하는 설정 클래스 |
2. @Component 어노테이션으로 자동 빈 등록하기
@Component
public class MemberDAO {
private final Map<Integer, MemberDTO> memberMap;
public MemberDAO() {
memberMap = new HashMap<>();
memberMap.put(1, new MemberDTO(1, "user01", "pass01", "홍길동"));
memberMap.put(2, new MemberDTO(2, "user02", "pass02", "유관순"));
}
/* 매개변수로 전달 받은 회원 번호를 map에서 조회 후 회원 정보를 리턴하는 메소드 */
public MemberDTO selectMember(int sequence) {
return memberMap.get(sequence);
}
/* 매개변수를 전달 받은 회원 정보를 map에 추가하고 성공 실패 여부를 boolean으로 리턴하는 메소드 */
public boolean insertMember(MemberDTO newMember) {
int before = memberMap.size();
memberMap.put(newMember.getSequence(), newMember);
int after = memberMap.size();
return after > before;
}
}
bean으로 등록하고자 하는 클래스 위에 @Component 어노테이션을 기재하면 스프링 컨테이너 구동 시 빈으로 자동 등록된다.
- 이름을 별도로 지정하지 않으면 클래스명의 첫 문자를 소문자로 변경하여 bean의 id로 자동 인식한다.
- @Component("myName") 또는 @Component(value="myName") 의 형식으로 bean의 id를 설정할 수 있다.
3. @ComponentScan 어노테이션으로 base packages 설정하기
@ComponentScan(basePackages="project")
public class ContextConfiguration {}
@ComponentScan어노테이션의 basePackagese 속성에 입력한 패키지가 빈 스캐닝의 범위가 된다.
스프링 컨테이너에 빈 스캐닝을 통해bean이 자동으로 등록 되고 생성 되었는지 확인한다.
ApplicationContext context
= new AnnotationConfigApplicationContext(ContextConfiguration.class);
/* getBeanDefinitionNames : 스프링 컨테이너에서 생성 된 bean들의 이름을 배열로 반환한다. */
String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
System.out.println("beanName : " + beanName);
}
/*
...생략
beanName : contextConfiguration
beanName : memberDAO
*/
4. excludeFilters
@ComponentScan 의 excludeFilters속성을 이용해서 일부 컴포넌트를 빈 스캐닝에서 제외할 수 있다.
- Type으로 설정하는 방법
@ComponentScan(basePackages="project",
excludeFilters={
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,
classes={MemberDAO.class})
})
public class ContextConfiguration {}
- Annotation 종류로 설정하는 방법
@ComponentScan(basePackages="project",
excludeFilters={
@ComponentScan.Filter(type=FilterType.ANNOTATION,
classes={org.springframework.stereotype.Component.class})
})
public class ContextConfiguration {}
- 표현식으로 설정하는 방법
@ComponentScan(basePackages="project",
excludeFilters={
@ComponentScan.Filter(type=FilterType.REGEX,
pattern={"annotationconfig.java.*"})
})
public class ContextConfiguration {}
빈 스캐닝에서MemberDAO클래스가 제외되어 아래 코드를 실행하면 해당 이름을 가진 빈이 없다는 오류가 발생한다.
ApplicationContext context = new AnnotationConfigApplicationContext(ContextConfiguration.class);
String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
System.out.println("beanName : " + beanName);
}
MemberDAO memberDAO = context.getBean("memberDAO", MemberDAO.class);
/*
...생략
beanName : contextConfiguration
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'memberDAO' available
*/
5. includeFilters
@ComponentScan 의 includeFilters속성을 이용해서 일부 컴포넌트를 빈 스캐닝에 포함 시킬 수 있다.
@ComponentScan(basePackages="project",
useDefaultFilters=false,
includeFilters={@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,
classes= {MemberDAO.class})
})
public class ContextConfiguration {}
useDefaultFilters 속성의 기본 값은 true로 @Component 종류의 어노테이션을 자동으로 등록 처리 해준다. 해당 속성을 false로 변경하면 컴포넌트 스캔이 일어나지 않게 된다.
별도로 includeFilters 속성을 정의해 컴포넌트 스캔이 발생하도록 한다.
excludeFilters에서 설정하는 방식과 동일하므로 종류별 예시는 생략한다.
아래 코드를 실행하면 빈 스캐닝에서MemberDAO클래스가 포함되어 해당 이름을 가진 빈을 확인할 수 있다.
ApplicationContext context
= new AnnotationConfigApplicationContext(ContextConfiguration.class);
String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
System.out.println("beanName : " + beanName);
}
/*
...생략
beanName : contextConfiguration
beanName : memberDAO
*/
6. XML에서 Component Scan 설정
아래와 같이 XML 설정 파일에서 Component Scan의base package를 설정할 수도 있다.
<?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
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="project"/>
</beans>
<context:component-scan> 태그는 context 네임스페이스의 기능이기 때문에 context: 접두어가 필요하다.
또한 XML 설정 파일의 기본 네임스페이스가 beans로 설정 되어 있기 때문에 context 네임스페이스 추가가 필요하다.
base package에@Component 어노테이션을 작성한 MemberDAOclass를 배치해 두고 아래와 같은 코드를 실행하면 빈이 등록 되어있음을 확인할 수 있다.
ApplicationContext context
= new GenericXmlApplicationContext("section03/javaannotation/spring-context.xml");
String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
System.out.println("beanName : " + beanName);
}
/*
beanName : memberDAO
...생략
*/
아래와 같이 <context:component-scan> 태그 내부에 <exclude-filter> 또는 <include-filter> 태그를 정의할 수 있다.
<include-filter> 의 경우 동일한 방식으로 정의하므로 생략하였다.
<?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
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="project">
<context:exclude-filter type="assignable" expression="common.MemberDAO"/>
</context:component-scan>
</beans>
빈 스캐닝에서MemberDAO클래스가 제외되어 아래 코드를 실행하면 해당 이름을 가진 빈이 없다는 오류가 발생한다.
ApplicationContext context
= new GenericXmlApplicationContext("section03/javaannotation/spring-context.xml");
String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
System.out.println("beanName : " + beanName);
}
MemberDAO memberDAO = context.getBean("memberDAO", MemberDAO.class);
/*
...생략
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException
: No bean named 'memberDAO' available
*/
정리
- XML 설정은 전통적으로 사용하던 방식으로 최근에는 Java 설정이 선호된다.
- 개발자가 직접 컨트롤 가능한 Class의 경우, @Component를 클래스에 정의하여 빈 스캐닝을 통한 자동 빈 등록을 한다.
- 개발자가 직접 제어할 수 없는 외부 라이브러리는 @Bean을 메소드에 사용하여 수동 빈 등록을 한다.
- 다형성을 활용하고 싶은 경우에도 @Bean을 사용할 수 있다.
Java-based Container Configuration :: Spring Framework
This section covers how to use annotations in your Java code to configure the Spring container.
docs.spring.io
'Java > Spring Framework' 카테고리의 다른 글
[Spring Framework] Spring Framework 의존성 주입(DI) 어노테이션 총정리 (5) | 2025.06.10 |
---|---|
[Spring Framework] Spring Boot에서 Dependency Injection 완벽 가이드 | 개념부터 실습까지 (1) | 2025.06.09 |
[Spring Framework] Spring IoC 컨테이너 사용법 완벽 정리 | 실전 예제로 이해하는 DI (0) | 2025.06.01 |
[Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의 (1) | 2025.05.29 |
[Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리 (0) | 2025.05.27 |