반응형
스프링 빈과 의존관계
컨포넌트 스캔과 자동 의존관계 설정
- 스프링은 스프링 컨테이너에서 객체를 생성하여 스프링 빈으로 등록한 후 관리한다.
- MemberController에서 MemberService을 가져와서 사용할 때 매번 new 하면 그때마다 새로운 객체가 생성된다.
- new 하지 않고 스프링 컨테이너에 객체를 생성한 다음 그 객체를 가져다가 쓰자
- 컨트롤러 뿐만 아니라 서비스, 리포지토리까지 @Service, @Repository로 스프링 컨테이너에 자동 등록해야 가져다 쓸 수 있다.
- 그 다음 @Autowired + 생성자 주입하여 컨테이너에 있는 객체를 연결한다.
컨포넌트 스캔 원리
- @Component : 이 어노테이션이 있으면 스프링 빈으로 자동 등록한다.
- 다음 어노테이션도 @Component를 포함하여 스프링 빈으로 자동 등록된다.
- @Controller
- @Service
- @Repository
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
자바 코드로 직접 스프링 빈 등록
- 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔 사용
- 반대로 정형화되지 않거나 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록
- 우리가 DB를 아직 정하지 않았다는 가상의 시나리오를 갖고 있기 때문에 리포지토리 인터페이스를 구축한 다음, 실제 리포지토리를 구현하였다. 나중에 DB를 정해 그것에 맞는 리포지토리를 만들 때 서비스나 컨트롤러 등 다른 코드는 건들이지 않고 구현하기 위해 스프링 빈으로 등록하는 것이 좋다.(즉, 우리는 리포지토리가 정형화 되지 않은 코드이므로 직접 스프링 빈을 등록한다.)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
스프링 컨테이너와 스프링 빈 이미지
스프링은 스프링 컨테이너에 스프링 빈을 등록할 때 하나만 등록해서 공유한다. 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. 이를 싱글톤이라고 한다.
회원 관리 예제 - 웹 MVC 개발
등록
@GetMapping("/members/new")
public String createForm() {
return "/members/createForm";
}
@PostMapping("/members/new")
public String create(MemberForm memberForm) {
Member member = new Member();
member.setName(memberForm.getName());
memberService.join(member);
return "redirect:/";
}
조회
@GetMapping("/members")
public String view(Model model) {
List<Member> members = memberService.findMembers();
model.addAttribute("members", members);
return "/members/viewMembers";
}
스프링 DB 접근 기술
JPA
기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다.
JPA 엔티티 매핑
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 시스템 상에서 회원 데이터를 구분하는 key
@Column
private String name;
...
JPA 회원 리포지토리
public class JPAMemberRepository implements MemberRepository{
private final EntityManager em;
public JPAMemberRepository(EntityManager em) {
this.em = em;
}
@Override
public Member save(Member member) {
em.persist(member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
Member member = em.find(Member.class, id);
return Optional.ofNullable(member);
}
@Override
public Optional<Member> findByName(String name) {
Member member = em.find(Member.class, name);
return Optional.ofNullable(member);
}
@Override
public List<Member> findAll() {
// 기존의 쿼리와 다르게 Member로 부터 받아온 객체를 그대로 사용한다.
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
}
- EntityManager : Entity 관리(모든 JPA의 동작은 Entity를 기준으로 돌아간다.)
- JPA는 기존의 쿼리 형식과 다르게 Member로부터 받아온 객체를 그대로 사용한다.
(select key, value from Member --> select m from Member (as) m)
서비스 계층에 트랜잭션 추가
import org.springframework.transaction.annotation.Transactional
@Transactional
public class MemberService {}
- JPA를 통한 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다.
JPA를 사용하도록 스프링 설정 변경
@Configuration
public class SpringConfig {
private EntityManager em;
@Autowired
public SpringConfig(EntityManager em) {
this.em = em;
}
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new JPAMemberRepository(em);
}
}
스프링 데이터 JPA
- 인터페이스를 통한 기본적인 CRUD
- findByName 등 메서드 이름 만으로 조회 기능 제공
- 페이징 기능 자동 제공
스프링 데이터 JPA 회원 리포지토리
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long> , MemberRepository{}
스프링 데이터 JPA 회원 리포지토리를 사용하도록 스프링 설정 변경
@Configuration
public class SpringConfig {
public MemberRepository memberRepository;
@Autowired
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Bean
public MemberService memberService() {
return new MemberService(memberRepository);
}
}
JPA 제공 클래스
public interface JpaRepository<T, ID> extends ListCrudRepository<T, ID>, ListPagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {}
반응형
'WINK-(Web & App) > Spring Boot 스터디' 카테고리의 다른 글
[2024-2 Spring Boot 스터디] 김문기 #2주 (0) | 2024.11.07 |
---|---|
[2024-2 SpringBoot 스터디] 조상혁 #2주차 (3) | 2024.11.06 |
(미완성)[2024-2 SpringBoot 스터디] 정호용 #1주차 섹션 5~9 (2) | 2024.11.05 |
[2024-2 Spring Boot 스터디] 백채린 #1주차 (0) | 2024.10.10 |
[2024-2 SpringBoot 스터디] 정호용 #1주차 섹션 1~4 (2) | 2024.10.10 |