인프런 커뮤니티 질문&답변

753cindy님의 프로필 이미지
753cindy

작성한 질문수

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

스프링 데이터 JPA

memberservice 어노테이션

작성

·

380

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;
// springbootapplication.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

753cindy님의 프로필 이미지
753cindy
질문자

추가로,

 

No qualifying bean of type 'hello.hellospring.repository.MemberRepository' available: expected single matching bean but found 2: memoryMemberRepository,springDataJpaMemberRepository

 

이 에러도 뜨던데 찾아보니 이건 bean이 중복등록된 게 맞다고 하더라구요. 강사님이 하신대로 위에 보시면 springconfig 에 memberrepository 모두 주석처리했는데, 에러가 그대로 뜨고 MemoryMemberRepository에서 @Repository 를 빼니까 잘되더라구요..? 이게 맞는걸까요..?

753cindy님의 프로필 이미지
753cindy

작성한 질문수

질문하기