작성
·
731
0
스프링 부트 메인에는 SpringBootApplication어노테이션이 붙어있고 여기서 컴포넌트 스캔을 하므로 AppConfig.java랑 AutoAppConfig.java를 둘다 스캔하는지 궁금합니다
둘다 스캔을 한다면 충돌이 생겨야 한다고 생각을 합니다 Appconfig.java에서 수동으로 등록하고 AutoAppConfig에서는 자동으로 컴포넌트 스캔을 한다면 각각 수동빈과 자동빈 이므로 충돌이 아닌가요..?
이상하게 Appconfig.java랑 AutoAppConfig.java는 수동빈 자동빈 문제같은데 충돌이 안나는 이유가 궁금하며AutoAppConfig에서 수동빈 등록시 왜 충돌이 생기는지 이해가 잘 안됩니다..
답변 2
1
1번 : "@Configuration과 바이트코드 조작의 마법" 부분에서 스프링이 Appconfig.java의 아래와 같은 코드로 싱글톤을 보장해준다고 하였는데 제가 이 아래의 코드를 보고 이해한바로는 이름이 같으면 그 이름으로 스프링 컨테이너를 조회한다 인데 자동빈(or수동빈)으로 같은 이름을 스캔시 왜 에러가 나는건지 궁금합니다 A라는 이름을 2개를 만들고 아래와 같은 루틴을 돌리면 에러가 안 발생하는게 아닌가요??
=> 빈 이름 중복 관점에서 자동이냐 수동이냐는 중요하지 않습니다. 동일한 이름을 가지는 빈이 존재하느냐가 중요합니다. 충돌을 방지하려면 이름을 다르게 해주세요.
2번 : 만약에 아래의 Config 파일을 통해 빈을 만들면 AutoAppConfig.java가 컴포넌트 스캔을 해서 MemberServiceImpl이라는 빈이 만들어지고 그 값으로 해당하는 객체 값을 가지고 있고 AppConfig.java 구성으로 memberService라는 빈이 생기고 (물론 다른 빈도 생기겠지만 하나의 빈만 예시로 들겠습니다)그 값으로 new MemberServiceImpl한 값을 가지고 있는 식으로 구성이 되는건지 궁금합니다
=> 이 부분은 제가 말씀드리는 것보다 직접 해보시는 게 빈 등록과 충돌에 대한 이해를 높일 수 있을 것 같습니다.
자동, 수동 빈 등록시 빈 이름이 어떻게 결정되는지에 초점을 맞추시고 테스트 해보시면 좋을 것 같습니다.
0
제가 스스로 실험을 해본 결과 질문에 대한 해답을 찾았습니다.
하지만 새로운 의문이 생겨서 다시 질문을 드리자면..
1번 : "@Configuration과 바이트코드 조작의 마법" 부분에서 스프링이 Appconfig.java의 아래와 같은 코드로 싱글톤을 보장해준다고 하였는데 제가 이 아래의 코드를 보고 이해한바로는 이름이 같으면 그 이름으로 스프링 컨테이너를 조회한다 인데 자동빈(or수동빈)으로 같은 이름을 스캔시 왜 에러가 나는건지 궁금합니다 A라는 이름을 2개를 만들고 아래와 같은 루틴을 돌리면 에러가 안 발생하는게 아닌가요??
2번 : 만약에 아래의 Config 파일을 통해 빈을 만들면 AutoAppConfig.java가 컴포넌트 스캔을 해서 MemberServiceImpl이라는 빈이 만들어지고 그 값으로 해당하는 객체 값을 가지고 있고 AppConfig.java 구성으로 memberService라는 빈이 생기고 (물론 다른 빈도 생기겠지만 하나의 빈만 예시로 들겠습니다)그 값으로 new MemberServiceImpl한 값을 가지고 있는 식으로 구성이 되는건지 궁금합니다
MemberServiceImpl
package hello.core.member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
//테스트용
public MemberRepository getMemberRepository(){
return memberRepository;
}
}
AutoAppConfig.java
package hello.core;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
public class AutoAppConfig {}
Appconfig.java
package hello.core;
import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import hello.core.member.MemberRepository;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import org.apache.commons.logging.Log;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService(){
return new OrderServiceImpl(memberRepository(),discountPolicy());
}
@Bean
public DiscountPolicy discountPolicy(){
return new RateDiscountPolicy();
}
}
넵 감사합니다!