728x90
반응형

[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 빈을 등록하는 설정 클래스

Spring 사진 1

 

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

728x90
반응형
728x90
반응형

[Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의

 

[Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의

[Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리 [Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리[Servlet] Servlet에서 Thread가 어떻게 작동하는가? 웹 개발자를 위한 완벽 가이드

crushed-taro.tistory.com

1. IoC Container 사용하기

  • 아래 코드는 테스트에 공통적으로 사용할MemberDTO클래스이다.
@Data
@AllArgsConstructor
public class MemberDTO {

    private int sequence;     //회원번호
    private String id;        //아이디
    private String pwd;       //비밀번호
    private String name;      //이름

}

 

1. XML - based Configuration

1. GenericApplicationContext

GenericXmlApplicationContext Spring IoC Container 중 하나이다. XML 형태의 Configuration Metadata를 사용하여 Bean을 생성한다.

/* GenericXmlApplicationContext 클래스를 사용하여 ApplicationContext를 생성한다. 
 * 생성자에 XML 설정 메타 정보를 인자로 전달한다. */
ApplicationContext context 
	= new GenericXmlApplicationContext("spring-context.xml"
		/*XML Configuration Metadata 파일 경로*/);

 

2. XML 기반 Configuration Metadata

XML 형태의 Configuration Metadata 파일은 다음과 같이 작성할 수 있다. 다음 예제에서는MemberDTO클래스의 객체를 Bean으로 등록하고 있다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
													 http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="member" class="MemberDTO">
				<!-- int 타입의 첫 번째 파라미터에 1 값을 전달 -->
        <constructor-arg index="0" value="1"/>
	      <!-- String 타입의 id 파라미터에 "user01" 값을 전달 -->
        <constructor-arg name="id" value="user01"/>
        <!-- String 타입의 세 번째 파라미터에 "pass01" 값을 전달 -->
        <constructor-arg index="2"><value>pass01</value></constructor-arg>
				<!-- String 타입의 name 파라미터에 "홍길동" 값을 전달 -->
        <constructor-arg name="name"><value>홍길동</value></constructor-arg>
    </bean>

</beans>

 

  • <beans>그는 Bean 설정 정보를 담고 있는 메타데이터를 정의하는 태그이다.
    • xmlns : XML Namespace를 정의
    • xmlns:xsi : XML Schema Instance Namespace를 정의
    • xsi:schemaLocation : XML Schema Location을 정의
    • XML Schema는 XML 문서의 구조와 유효성을 검사하기 위한 언어로, XML Schema Definition(XSD) 파일을 통해 정의
  • <beans> 태그 내부에 <bean>그를 사용해 하나의 bean 설정 정보를 작성할 수 있다.
    • id : Bean의 이름을 정의
    • class : 객체의 클래스를 지정
  • <constructor-arg> 태그는 생성자를 호출할 때 전달할 인자를 정의한다. 만약 <bean> 태그 내부에 아무 것도 작성하지 않으면 기본 생성자를 사용한다는 의미이다.
    • index : 메서드의 파라미터 순서(index)로 전달
    • name : 파라미터 이름으로 전달
    • value : 파라미터 값으로 전달

 

3. GenericApplicationContext(스프링 컨테이너) 생성 테스트

GenericApplicationContext에 bean등록 되고 생성 되었는지 확인한다.

  • bean의 id를 이용해서 bean을 가져오는 방법
MemberDTO member = (MemberDTO) context.getBean("member");
System.out.println(member);

//MemberDTO(sequence=1, id=user01, pwd=pass01, name=홍길동)

 

  • bean의 클래스 메타 정보를 전달하여 가져오는 방법
MemberDTO member = context.getBean(MemberDTO.class);
System.out.println(member);

//MemberDTO(sequence=1, id=user01, pwd=pass01, name=홍길동)

 

  • bean의 id와 클래스 메타 정보를 전달하여 가져오는 방법
MemberDTO member = (MemberDTO) context.getBean("member");
System.out.println(member);

//MemberDTO(sequence=1, id=user01, pwd=pass01, name=홍길동)

 

2. Java-based Configuration

1. AnnotationConfigApplicationContext

AnnotationConfigApplicationContext는 Spring IoC Container 중 하나이다. Java Configuration 형태의 Configuration Metadata를 사용하여 Bean을 생성한다.

/* AnnotationConfigApplicationContext클래스를 사용하여 ApplicationContext를 생성한다. 
 * 생성자에 @Configuration 어노테이션이 달린 설정 클래스의 메타 정보를 전달한다. */
ApplicationContext context 
	= new AnnotationConfigApplicationContext(ContextConfiguration.class);

 

2. Java 기반 Configuration Metadata

Java Configuration 형태의 Configuration Metadata 파일은 다음과 같이 작성할 수 있다. 다음 예제에서는MemberDTO래스의 객체를 Bean으로 등록하고 있다.

@Configuration
public class ContextConfiguration {

    @Bean(name="member")
    public MemberDTO getMember() {

        return new MemberDTO(1, "user01", "pass01", "홍길동");
    }

}

 

@Configuration 어노테이션은 해당 클래스가 빈을 생성하는 클래스임을 표기한다.

 

  • @Bean 어노테이션은 해당 메소드의 반환 값을 스프링 컨테이너에 빈으로 등록한다는 의미이다.
    • 이름을 별도로 지정하지 않으면 메소드 이름을 bean의 id로 자동 인식한다.
    • @Bean("myName") 또는 @Bean(name="myName") 의 형식으로 bean의 id를 설정할 수 있다.

 

3. AnnotationConfigApplicationContext(스프링 컨테이너) 생성 테스트

AnnotationConfigApplicationContext에 bean 이 등록 되고 생성 되었는지 확인한다.

MemberDTO member = context.getBean("member", MemberDTO.class);
System.out.println(member);

//MemberDTO(sequence=1, id=user01, pwd=pass01, name=홍길동)
728x90
반응형
728x90
반응형

에러가 난 이유.

Spring Boot가 JPA Repository 빈을 애플리케이션 컨텍스트에 등록하지 못해서 발생한 것.

 

해결 방안.

@SpringBootApplication
@ComponentScan(path)
@EntityScan(basePackages = path)
@EnableJpaRepositories(basePackages = path)
public class Application {

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

 

  • Application위에 어노테이션을 추가하였음.
  • 엔티티 및 레포지토리 인터페이스를 Bean(= Entity)으로 인식시키기 위한 설정.

 

728x90
반응형

+ Recent posts