하나씩 차근차근
article thumbnail

앞에서 만든 예제 코드에 스프링을 사용해보겠습니다.

 

시작

먼저 Appconfig 에 @Configuration 과 @Bean 애노테이션을 붙여주겠습니다.

package hello.core;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import hello.core.member.MemberRepository;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.DiscountPolicy;
import hello.core.order.FixDiscountPolicy;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import hello.core.order.RateDiscountPolicy;

@Configuration
public class Appconfig {
	
	@Bean
	public MemberRepository memberRepository() {
		return new MemoryMemberRepository();
	}
	
	@Bean
	public DiscountPolicy discountPolicy() {
		// return new FixDiscountPolicy();
		return new RateDiscountPolicy();
	}
	
	@Bean
	public OrderService orderService() {
		return new OrderServiceImpl(memberRepository(), discountPolicy());
	}
	
	@Bean
	public MemberService memberService() {
		return new MemberServiceImpl(memberRepository());
	}
}
  • 스프링 컨테이너는 @Configuration 이 붙은 AppConfig 를 설정 정보로 사용
  • @Configuration 이 붙은 Appconfig 에서 @Bean 이 붙은 모든 메서드를 호출해서 반환된 객체를 컨테이너에 등록
  • 컨테이너에 등록된 객체를 스프링 빈이라고 하며, 메서드의 이름을 스프링 빈의 이름으로 사용

 

스프링 컨테이너 생성

스프링 컨테이너는 XML 기반으로 만드는 방법과 위에서 사용한 애노테이션으로 만드는 두가지 방식이 있습니다.

ApplicationContext applicationContext 
	= new AnnotationConfigApplicationContext(AppConfig.class);

애노테이션으로 만든 Appconfig 를 스프링 컨테이너 인페이스인 ApplicationContext 통해 컨테이너를 생성합니다.

스프링 컨테이너를 생성할때 구성 정보를 지정해줘야 합니다.

new AnnotationConfigApplicationContext (구성정보)

스프링 컨테이너는 파라미터로 전달받은 구성 정보를 사용해서 @Bean 이 붙은 메서드를 찾아서 스프링 빈을 등록합니다.

빈 이름은 메서드 이름을 사용하며, 직접 부여할 수 있습니다.

@Bean(name = "newmemberServie")
주의할 점은 빈 이름은 항상 다른 이름을 부여해야 합니다.

다음으로 스프링 컨테이너는 설정 정보를 참고해서 의존관계를 주입합니다.

 

스프링 빈 조회

위에서 만든 스프링 컨테이너를 통해 스프링 빈을 조회해보겠습니다.

src/test/java 디렉토리에 테스트를 할 수 있는 ApplicationContext 클래스를 만들겠습니다.

 

모든 빈 조회

package hello.core;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ApplicationContext {

	AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Appconfig.class);
	
	@Test
	void findAllBean() {
		String[] beanDefinitionNames = ac.getBeanDefinitionNames();
		
		for(String beanDefinitionName : beanDefinitionNames) {
			Object bean = ac.getBean(beanDefinitionName);
			System.out.println("name = " + beanDefinitionName + " object = " + bean);
		}
	}
}

위와 같이 Appconfig.class 의 설정 정보를 통해 스프링 컨테이너에서 빈을 읽어서 등록합니다.

name = org.springframework.context.annotation.internalConfigurationAnnotationProcessor object = org.springframework.context.annotation.ConfigurationClassPostProcessor@4e70a728
name = org.springframework.context.annotation.internalAutowiredAnnotationProcessor object = org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@b7838a9
name = org.springframework.context.annotation.internalCommonAnnotationProcessor object = org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@696f0212
name = org.springframework.context.event.internalEventListenerProcessor object = org.springframework.context.event.EventListenerMethodProcessor@5733f295
name = org.springframework.context.event.internalEventListenerFactory object = org.springframework.context.event.DefaultEventListenerFactory@1c3146bc
name = appconfig object = hello.core.Appconfig$$SpringCGLIB$$0@56c698e3
name = memberRepository object = hello.core.member.MemoryMemberRepository@47a86fbb
name = discountPolicy object = hello.core.order.RateDiscountPolicy@f478a81
name = orderService object = hello.core.order.OrderServiceImpl@19553973
name = memberService object = hello.core.member.MemberServiceImpl@7bb6ab3a

출력결과를 보면 스프링 자체 빈들과 함께 Appconfig 에 등록한 빈들이 출력됩니다.

Appconfig 또한 빈으로 등록되어 관리됩니다.

 

설정 정보의 빈 조회

설정 정보인 Appconfig 에 등록한 빈을 조회하기 위해서는 아래와 같은 명령어를 사용합니다.

  • ac.getBean(빈이름, 타입)
  • ac.getBean(타입)
package hello.core;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import hello.core.member.MemberService;

public class ApplicationContext {

	AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Appconfig.class);
	
	@Test
	void findBeanByName() {
		MemberService memberSerivce = ac.getBean("memberService", MemberService.class);
		System.out.println("memberSerivce = " + memberSerivce);
		System.out.println("memverService.getClass() = " + memberSerivce.getClass());
	}
}

위와 같이 MemberService.class 타입의 memberSerivce 라는 이름을 같은 빈을 조회하면 다음과 같이 출력됩니다.

memberSerivce = hello.core.member.MemberServiceImpl@4e70a728
memverService.getClass() = class hello.core.member.MemberServiceImpl

다음과 같이 타입으로 조회해도 결과는 같습니다.

package hello.core;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import hello.core.member.MemberService;

public class ApplicationContext {

	AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Appconfig.class);
	
	@Test
	void findBeanByType() {
		MemberService memberSerivce = ac.getBean(MemberService.class);
		System.out.println("memberSerivce = " + memberSerivce);
		System.out.println("memverService.getClass() = " + memberSerivce.getClass());
	}
}

 

xml 기반 사용법

위에서 사용한 Appconfig.class 를 xml 기반으로 만들어보겠습니다.

src/main/resources 에 appConfig.xml 파일을 만들고 아래와 같이 작성합니다.

<?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="memberService" class="hello.core.member.MemberServiceImpl">
		<constructor-arg name="memberRepository" ref="memberRepository"/>
	</bean>
	
	<bean id="memberRepository" class="hello.core.member.MemoryMemberRepository">
	
	</bean>
	
	<bean id="orderService" class="hello.core.order.OrderServiceImpl">
		<constructor-arg name="memberRepository" ref="memberRepository"/>
		<constructor-arg name="discountPolicy" ref="discountPolicy"/>
	</bean>
	
	<bean id="discountPolicy" class="hello.core.order.RateDiscountPolicy">
	</bean>
	
</beans>

다음으로 appConfig.xml 을 설정 정보로 사용해보겠습니다.

ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");

xml 파일을 설정 정보로 사용하기 위해서는 GenericXmlApplicationContext 를 사용합니다.

package hello.core;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import hello.core.member.MemberService;

public class XmlAppContext {
	
	ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");

	@Test
	void xmlAppContext() {
		MemberService memberSerivce = ac.getBean("memberService", MemberService.class);
		System.out.println("memberSerivce = " + memberSerivce);
		System.out.println("memverService.getClass() = " + memberSerivce.getClass());
	}
}

xml 설정 정보를 사용하는 XmlAppContext 클래스를 생성하고 실행을 합니다.

memberSerivce = hello.core.member.MemberServiceImpl@736caf7a
memverService.getClass() = class hello.core.member.MemberServiceImpl

실행을 하면 memberService 라는 이름으로 등록된 빈을 갖고 오는것을 확인할 수 있습니다.

profile

하나씩 차근차근

@jeehwan_lee

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!