작성
·
389
0
안녕하세요,
강의 진행중 아래와 같은 에러가 떠서 보니 memberservice가 중복되서 등록이 되어있다고 하는 것 같은데요,
Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'memberService' defined in class path resource [hello/hellospring/SpringConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=springConfig; factoryMethodName=memberService; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [hello/hellospring/SpringConfig.class]] for bean 'memberService': There is already [Generic bean: class [hello.hellospring.service.MemberService]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Users\63328\git\hello-spring\hello-spring\out\production\classes\hello\hellospring\service\MemberService.class]] bound.
아래처럼 세팅이 되어있었는데, memberserivce.java에 @memberservice 어노테이션을 지우면 잘 돌더라구요. 중복되서 bean이 등록되어서 그런건가요? SpringDataJpaMemberRepository.java랑 Memberservice.java에서 두번 등록된건가요?
Memberservice.java
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Transactional // jpa를 쓰려면 항상 transcation이 있어야함
@Service // 이게 없으면 그냥 순수한 자바코드
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
/**
* 회원가입
*/
public Long join(Member member) {
//같은 이름이 있는 중복 회원은 안됨!
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member) {
/**
Optional<Member> result = memberRepository.findByName(member.getName());
ifPresent 이란? result의 값이 있으면 동작. Optional에서만 동작
result.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
**/
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
/**
* 전체 회원 조회
*/
public List<Member> findMembers() {
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId) {
return memberRepository.findById(memberId);
}
}
--------------------------------
SpringConfig.java
package hello.hellospring;
import hello.hellospring.repository.JdbcMemberRepository;
import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.JpaMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.sql.DataSource;
// 어셈블리 코드
// OCP : 개방 - 폐쇄 원칙
@Configuration
public class SpringConfig {
private final MemberRepository memberRepository;
@Autowired
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
/**
@PersistenceContext
private EntityManager em;
//private DataSource dataSource;
// springboot가 application.properties를 보고 자체적으로 bean생성. 즉, datasource 생성.
@Autowired
public SpringConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
@Autowired
public SpringConfig(EntityManager em) {
this.em = em;
}
**/
@Bean // spring bean 등록
public MemberService memberService() {
//return new MemberService(memberRepository());
return new MemberService(memberRepository);
}
/**
@Bean
public MemberRepository memberRepository() {
//return new MemoryMemberCloneRepository();
//return new JdbcMemberRepository(dataSource);
//return new JdbcTemplateMemberRepository(dataSource);
//return new JpaMemberRepository(em);
return new JpaMemberRepository(em);
}
**/
}
-----------
SpringDataJpaMemberRepository.java
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
// springdataJPA가 JpaRepository 를 상속하고 있으면 자동으로 구현체를 spring bean에 등록해줌
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
@Override
Optional<Member> findByName(String name);
}
답변 2
1
안녕하세요. 753cindy님, 공식 서포터즈 OMG입니다.
본문 질문에 대한 답변은 생각하신게 맞습니다.
설정 파일(SpringConfig)에서도 MemberService에 대한 빈등록과
MemberService.java에서 @Service 어노테이션으로도 빈을 등록하여 동일한 빈 등록 오류로 보시면 됩니다.
추가 질문에 대한 것도 비슷하게 보시면 됩니다.
MemoryMemberRepository와 SpringDataJpaRepository가 빈으로 등록되어 발생한 것으로 Member에 대한 저장소를 하나만 지정하여야 하는데 2개 이상 등록하여 발생한 오류입니다.
감사합니다.
0
추가로,
No qualifying bean of type 'hello.hellospring.repository.MemberRepository' available: expected single matching bean but found 2: memoryMemberRepository,springDataJpaMemberRepository
이 에러도 뜨던데 찾아보니 이건 bean이 중복등록된 게 맞다고 하더라구요. 강사님이 하신대로 위에 보시면 springconfig 에 memberrepository 모두 주석처리했는데, 에러가 그대로 뜨고 MemoryMemberRepository에서 @Repository 를 빼니까 잘되더라구요..? 이게 맞는걸까요..?