개발하는 자몽

[Spring]빈 등록과 의존관계 주입 본문

Java/Spring

[Spring]빈 등록과 의존관계 주입

jaamong 2022. 8. 4. 15:19

수동 빈 등록과 의존관계 주입

@Bean 애노테이션은 method-level로 수동으로 빈을 등록할 때 사용한다. 메서드가 선언된 클래스 상단에는 @Configuration 애노테이션을 붙여 설정 정보 클래스임을 알려주고, 싱글톤이 깨지지 않도록 한다. (@Configuration을 붙이지 않아도 @Bean을 붙이면 다 빈으로 동록 되지만 싱글톤이 깨진다.)

/*
수동 빈 등록 및 의존관계 주입
@Configuration, @Bean
*/

package hello.core;

...

@Configuration
public class AppConfig {
	
    @Bean
    public MemberService memberService() {
    	//memberService에 의존관계로 memberRepository 주입
    	return new MemberServiceImpl(memberRepository()); 
    }
    
    @Bean
    public MemberRepository memberRepository() {
    	return new MemoryMemberRepository();
    }
    
    @Bean
    public OrderService orderService() {
    	//orderService에 의존관계로 memberRepository, discountPolicy 주입
    	return new OrderServiceImpl(memberRepository(), discountPolicy());
    }
    
    @Bean
    public DiscountPolicy discountPolicy() {
    	return new RateDiscountPolicy();
    }
}

각 메소드 상단에 위치한 @Bean 애노테이션은 메서드 이름으로 스프링 빈을 스프링 컨테이너에 등록한다는 의미이다. 

이러한 설정정보 클래스나 파일을 이용하여 DIP, OCP를 준수하여 의존관계를 주입할 수 있다. 위 예제를 이용하자면, MemberServiceImpl, OrderSerivceImpl의 생성자를 호출하면 의존관계 주입이 처리된다.  스프링은 이러한 동적인 객체 인스턴스 의존관계를 다 연결해준다. (객체의 참조값이 연결됨)

 

Note  @Configuration 스프링 공식 문서 - Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime, for example: ..

 

 

자동 빈 등록과 의존관계 주입

@ComponentScan 애노테이션은 @Component 애노테이션이 붙은 클래스를 자동으로 빈으로 등록한다. @Configuration 애노테이션도 붙여줘서 설정 정보 클래스임을 알려주고 싱글톤을 깨뜨리지 않도록 한다. 

/*
자동 빈 생성과 의존관계 주입
@Configuration, @ComponentScan
*/

package hello.core;

...

@Configuration
@ComponentScan
public class AutoAppConfig {
}

Note  @Configuration 애노테이션 안에는 @Component 애노테이션이 포함되어있어서 해당 애노테이션이 붙은 클래스도 빈으로 등록한다.

 

자동으로 빈을 생성하고 의존관계를 주입할 때는 @Bean 애노테이션과 함께 빈으로 등록할 메서드와 의존관계로 주입할 메서드를 다 입력했다. 자동의 경우 수동으로 빈을 등록하는 것에 비해 코드가 간결하다. 하지만 이 경우 의존관계를 어떻게 주입해야 할까.  

위 예제를 이용하면, MemberServiceImpl와 OrderServiceImpl 생성자 위에 @Autowired 애노테이션을 붙이면 된다.

//MemberService

package hello.core.member;

...

@Component
public class MemberServiceImpl implement MemberService {
	private final MemberRepository memberRepository;
	
    	@Autowired
	public MemberService(MemberRespotiroy memberRepository) {
		this.memberRepository = memberRepository;
	}
	...
}

// -------------------------------------------------------------------------

//OrderService

package hello.core.order;

...

@Component
public class OrderServiceImpl implement OrderSerivce {

	private final MemberRepository memberRepository;
	private final DiscountPolicy discountPolicy;

	@Autowired
	public OrderService(MemberRepository memberRepository, DiscountPolicy discountPolicy) {\
    		this.memberRepository = memberRepository;
        	this.discountPolicy = discountPolicy;
	}
    ...
}

또힌 위에서 언급한 것처럼 빈으로 등록하기 위해 클래스 상단에 @Compoent 애노테이션을 붙여주면 된다. 마찬가지로 의존관계로 주입되는 클래스(구현체)의 상단 위에도 @Component 애노테이션을 붙여준다.

 

따라서 @ComponentScan을 사용하면 @Autowired를 사용해야 한다. 빈이 자동으로 등록되는데 의존관계를 수동으로 등록할 수 없기 때문이다. 

 

@ComponentScan은 @Component가 붙은 클래스를 찾아 빈으로 등록한다고 했는데, 기본적으로 @ComponentScan이 붙은 클래스가 속한 패키지를 시작으로 모든 클래스를 찾는다. 또한 basePackage나 basePackageClasses를 지정하면 원하는 탐색 시작 위치를 지정할 수 있다.

/*
	basePackages 또는 basePackageClasses가 없으면
	default로 @ComponentScan이 붙은 클래스가 속한 패키지가 탐색 시작 위치다.
*/


package hello.core;

...

@Configuration
@ComponentScan(
//		basePackages = "hello.core" //hello.core 패키지를 시작으로 탐색
//		basePackageClasses = AutoAppConfig.class //이 클래스가 속한 패키지를 시작으로 탐색
)
public class AutoAppConfig {
}

'Java > Spring' 카테고리의 다른 글

프록시(Proxy)  (0) 2022.08.13
Dependency LookUp  (0) 2022.08.12
AnnotationConfigApplicationContext와 static class  (0) 2022.08.03
스프링 부트 공부 (10), AOP  (0) 2022.03.20
스프링 부트 공부 (9), 스프링 DB 접근 기술  (0) 2022.03.12
Comments