Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 스프링 mvc2 - 타임리프
- 자바의 정석 기초편 ch4
- 코드로 시작하는 자바 첫걸음
- 자바의 정석 기초편 ch6
- 자바의 정석 기초편 ch5
- 2024 정보처리기사 수제비 실기
- 자바 기본편 - 다형성
- 자바의 정석 기초편 ch8
- 자바의 정석 기초편 ch12
- 스프링 고급 - 스프링 aop
- 자바의 정석 기초편 ch11
- jpa 활용2 - api 개발 고급
- 게시글 목록 api
- 2024 정보처리기사 시나공 필기
- 자바의 정석 기초편 ch14
- 자바의 정석 기초편 ch3
- 스프링 db1 - 스프링과 문제 해결
- 자바의 정석 기초편 ch7
- 스프링 db2 - 데이터 접근 기술
- @Aspect
- 스프링 mvc1 - 스프링 mvc
- 스프링 입문(무료)
- 자바의 정석 기초편 ch2
- 스프링 mvc2 - 로그인 처리
- 스프링 mvc1 - 서블릿
- 스프링 mvc2 - 검증
- jpa - 객체지향 쿼리 언어
- 자바의 정석 기초편 ch1
- 자바의 정석 기초편 ch13
- 자바의 정석 기초편 ch9
Archives
- Today
- Total
나구리의 개발공부기록
스프링 빈과 의존관계 - 컴포넌트스캔과 자동 의존관계 설정, 자바 코드로 직접 스프링 빈 등록 / 회원 관리 예제 - 웹 MVC개발(홈 화면 추가, 회원등록, 회원조회) 본문
인프런 - 스프링 완전정복 코스 로드맵/코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술(무료)
스프링 빈과 의존관계 - 컴포넌트스캔과 자동 의존관계 설정, 자바 코드로 직접 스프링 빈 등록 / 회원 관리 예제 - 웹 MVC개발(홈 화면 추가, 회원등록, 회원조회)
소소한나구리 2024. 1. 24. 11:42컴포넌트스캔과 자동 의존관계 설정
- 회원 컨트롤러가 회원서비스를 통해서 회원가입 및 데이터 조회를 해야 함 (서로 의존관계가 있다고 표현)
멤버 컨트롤러 작성
- @Controller 애노테이션을 생성하면 스프링이 작성된 클래스의(컨트롤러) 객체를 생성해서 가지고 있음
- 해당 작업을 스프링 컨테이너에서 스프링 빈이 관리 된다고 표현 함
- 생성자에 @Autowired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어줌
-> 의존 관계를 외부에서 넣어주는 것을(Dependency Injection) 의존성 주입이라고 함
package start.startspring.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import start.startspring.service.MemberService;
@Controller
public class MemberController {
// new 연산자로 객체 생성을 하지않고 spring 컨테이너에서 받아서 쓰도록 해야함
private final MemberService memberService;
// 생성자에 @Autowired 애노테이션을 붙이면 매개변수를 스프링이 컨테이너에 있는 멤버 서비스를 가져다가 연결시킴
// 매개변수의 타입 클래스에 @Service 애노테이션을 붙여 줘야 함
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
컴포넌트 스캔과 자동 의존관계 설정으로 스프링 빈 등록
- @Component 애노테이션이 있으면 스프링 빈으로 자동 등록
- @Controller 컨트롤러가 스프링 빈으로 자동 등록 된 이유도 컴포넌트 스캔 때문
- @Controller, @Service, @Repository도 스프링 빈으로 자동 등록
- 각 애노테이션에 들어가보면 모두 @Component가 등록 되어 있음
멤버 서비스와 멤버리포지토리의 구현체인 메모리멤버리포지토리의 클래스에 각각 애노테이션을 작성
- memberService와 memberRepository가 스프링컨테이너에 스프링 빈으로 등록 됨
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Repository
public class MemoryMemberRepository implements MemberRepository {
// 실무에서는 공유되는 변수일 경우 ConcurrentHashMap을 써야하지만 예제는 단순하게 HashMap사용
private Map<Long, Member> store = new HashMap<>();
// 위와 마찬가지로 실무에서는 AtomicLong을 사용
private static long sequence = 0L;
PS.
- 생성자에 @Autowired를 사용 하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입
(생성자가 1개인 경우 애노테이션 생략 가능) - 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때 기본적으로 싱글톤으로 등록하여 유일한 인스턴스를 공유함
- 같은 스프링 빈이면 모두 같은 인스턴스
- 설정으로 싱글톤이 아니게 할 수 있으나 특별한 경우를 제외하면 대부분 싱글톤을 사용
자바 코드로 직접 스프링 빈 등록
- 직접 코드로 스프링 빈을 등록 한다고해도 Controller는 클래스에 @Controller와 생성자에 @Autowired를 그대로 두고 나머지 애노테이션들만 제거하고 진행
package start.startspring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import start.startspring.repository.MemberRepository;
import start.startspring.repository.MemoryMemberRepository;
import start.startspring.service.MemberService;
@Configuration
public class SpringConfig {
// Bean을 등록
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
- XML로 설정하는 방식도 있지만 최근에는 잘 사용하지 않음
- DI(Dependency Injection)에는 필드주입, setter주입, 생성자 주입 3가지 방법이 있음
-> 의존관계가 실행 중 동적으로 변하는경우는 없으므로 생성자 주입을 권장 - 실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용
- 정형화 되지 않거나 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈 등록
필드 주입 방식 - 권장하지 않음
- 중간에 바꿀 수 있는 방법이 전혀 없음
@Controller
public class MemberController {
// 인텔리제이에서 경고를 표시
@Autowired private MemberService memberService;
}
setter 주입 방식 - 권장하지 않음
- 메서드가 public으로 노출 되어있기 때문에 위험성이 높음
- 변경 되지 말아야할 메서드가 호출이 될 수 있으면 위험
@Controller
public class MemberController {
// final이 없음
private MemberService memberService;
@Autowired
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}
}
주의사항
- @Autowired를 통한 DI는 스프링이 관리하는 객체에서만 동작(스프링 빈에 등록)
- 내가 직접 객체를 생성하거나 스프링 빈에 등록하지 않으면 동작하지 않음
회원 웹 기능 - 홈 화면 추가
- HomeController class 작성
package start.startspring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
}
- home.html templates 작성
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
<div>
<h1>Hello Spring</h1>
<p>회원 기능</p>
<p>
<a href="/members/new">회원 가입</a>
<a href="/members">회원 목록</a>
</p>
</div>
</div>
</body>
</html>
- 실행 후 localhost:8080 접속 -> 정상
리마인드
- 웹 브라우저 요청 -> 톰캣 서버 -> 맵핑 된 컨트롤러 확인 후 반환 -> 없으면 static파일 찾아서 반환
회원 웹 기능 - 등록
- MemberForm class 작성 (웹에서 받은 값을 저장)
package start.startspring.controller;
public class MemberForm {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- createMemberForm templates작성 (회원 등록을 받을 페이지)
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
<form action="/members/new" method="post"> <!--전달방식 = post-->
<div class="form-group">
<label for="name">이름</label>
<input type="text" id="name" name="name" placeholder="이름을 입력하세요">
</div>
<button type="submit">등록</button>
</form>
</div>
</body>
</html>
- MemberController에 웹에서 입력된(createMemberForm)값을 Post형식으로 받아서 MemberService에 저장
@Controller
public class MemberController {
// new 연산자로 객체 생성을 하지않고 spring 컨테이너에서 받아서 쓰도록 해야함
private final MemberService memberService;
// 생성자에 @Autowired 애노테이션을 붙이면 매개변수를 스프링이 컨테이너에 있는 멤버 서비스를 가져다가 연결시킴
// 매개변수의 타입 클래스에 @Service 애노테이션을 붙여 줘야 함
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
@GetMapping("/members/new")
public String createForm() {
return "members/createMemberForm.html";
}
// 보통 data를 등록할때는 post 조회할 땐 get을 사용
@PostMapping("/members/new")
public String create(MemberForm form) {
Member member = new Member();
member.setName(form.getName());
memberService.join(member);
return "redirect:/";
}
}
회원 웹 기능 - 조회
- MemberController class에 GetMapping 방식의 메서드 추가
@GetMapping("/members")
public String list(Model model) {
List<Member> members = memberService.findMembers();
model.addAttribute("members", members);
return "members/memberList";
}
}
- memberList template 작성
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
<div>
<table>
<thead>
<tr>
<th>#</th>
<th>이름</th> </tr>
</thead>
<tbody>
<!--thymeleaf 문법-->
<tr th:each="member : ${members}"> <!--Model안에 있는 값을 꺼냄-->
<!--getId메서드를 통해 Member에 있는 id값을 호출해서 꺼냄-->
<td th:text="${member.id}"></td>
<!--getName메서드를 통해 Member에 있는 name값을 호출해서 꺼냄-->
<td th:text="${member.name}"></td>
</tr>
</tbody>
</table>
</div>
</div> <!-- /container -->
</body>
</html>
- 실행 결과
출처 : 인프런 - 스프링 입문(무료) / 김영한님
'인프런 - 스프링 완전정복 코스 로드맵 > 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술(무료)' 카테고리의 다른 글
스프링 DB 접근 기술 2 - 스프링 JdbcTemplate, JPA, 스프링 데이터 JPA / AOP - AOP가 필요한 상황, AOP적용 (1) | 2024.01.24 |
---|---|
스프링 DB 접근 기술 1 - H2데이터베이스 설치, 순수JDBC, 스프링 통합 테스트 (0) | 2024.01.24 |
회원관리 예제 - 비즈니스 요구사항 정리, 회원 도메인과 리포지토리 만들기, 테스트 케이스 작성, 회원 서비스 개발, 서비스 테스트 (1) | 2024.01.23 |
스프링 웹 개발 기초 - 정적 콘텐츠, MVC와 템플릿 엔진, API (2) | 2024.01.23 |
프로젝트 환경설정 - 프로젝트생성, 라이브러리 탐색, View환경설정, 빌드 및 실행 (1) | 2024.01.22 |