Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions solution/week06/Problem1.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ interface BookService {
// MemoryBookRepository에 @Component를 붙여서
// 컴포넌트 스캔 시 스프링이 자동으로 빈으로 등록하게 하세요.
// ──────────────────────────────────────────────────────────────────────
@Component
static class MemoryBookRepository implements BookRepository {
private final Map<Long, Book> store = new HashMap<>();

Expand All @@ -99,21 +100,28 @@ public Book findById(Long id) {
// 힌트: 생성자가 딱 1개면 @Autowired를 생략해도 자동 주입됩니다.
// 하지만 이번엔 명시적으로 붙여봅시다!
// ──────────────────────────────────────────────────────────────────────
@Component
static class BookServiceImpl implements BookService {

// TODO ②: private final BookRepository bookRepository;
private final BookRepository bookRepository;

// TODO ③: @Autowired 생성자 작성
@Autowired
public BookServiceImpl (BookRepository bookRepository) {
this.bookRepository = bookRepository;
}

@Override
public void register(Book book) {
// TODO ④: bookRepository.save(book) 호출
bookRepository.save(book);
}

@Override
public Book findBook(Long id) {
// TODO ④: return bookRepository.findById(id)
return null;
return bookRepository.findById(id);
}
}

Expand All @@ -127,6 +135,8 @@ public Book findBook(Long id) {
// 참고: @Bean 메서드는 작성하지 않아도 됩니다.
// @ComponentScan이 @Component 클래스들을 알아서 찾아 등록해줍니다.
// ──────────────────────────────────────────────────────────────────────
@ComponentScan
@Configuration
static class AutoAppConfig {
// 비어 있어도 괜찮습니다!
}
Expand All @@ -135,18 +145,18 @@ static class AutoAppConfig {
// main: TODO를 모두 완성한 후 아래 주석을 해제하고 실행해보세요.
// ──────────────────────────────────────────────────────────────────────
public static void main(String[] args) {
// AnnotationConfigApplicationContext ac =
// new AnnotationConfigApplicationContext(AutoAppConfig.class);
// BookService bookService = ac.getBean(BookService.class);
//
// Book book = new Book(1L, "스프링 핵심 원리", "김영한");
// bookService.register(book);
//
// Book found = bookService.findBook(1L);
// System.out.println("등록한 도서: " + book.getTitle());
// System.out.println("조회한 도서: " + found.getTitle());
// System.out.println("일치 여부: " + book.getTitle().equals(found.getTitle()));
//
// ac.close();
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext(AutoAppConfig.class);
BookService bookService = ac.getBean(BookService.class);

Book book = new Book(1L, "스프링 핵심 원리", "김영한");
bookService.register(book);

Book found = bookService.findBook(1L);
System.out.println("등록한 도서: " + book.getTitle());
System.out.println("조회한 도서: " + found.getTitle());
System.out.println("일치 여부: " + book.getTitle().equals(found.getTitle()));

ac.close();
}
}
49 changes: 30 additions & 19 deletions solution/week06/Problem2.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public void sendOrder(String item) {
// 빈 초기화 완료 직후 이 메서드가 자동으로 호출되도록
// @PostConstruct 애노테이션을 붙이세요.
// ──────────────────────────────────────────────────────────────────
@PostConstruct
public void init() {
System.out.println("[init] CafeConnection 초기화");
connect();
Expand All @@ -87,6 +88,7 @@ public void init() {
// 빈 소멸 직전에 이 메서드가 자동으로 호출되도록
// @PreDestroy 애노테이션을 붙이세요.
// ──────────────────────────────────────────────────────────────────
@PreDestroy
public void close() {
System.out.println("[close] CafeConnection 종료");
disconnect();
Expand All @@ -109,6 +111,7 @@ public void close() {
// OrderCounter가 스프링 컨테이너에 요청할 때마다 새로 생성되도록
// @Scope("prototype") 을 추가하세요.
// ──────────────────────────────────────────────────────────────────────
@Scope("prototype")
@Component
static class OrderCounter {
private int count = 0;
Expand Down Expand Up @@ -152,14 +155,22 @@ static class CafeOrderService {
// ──────────────────────────────────────────────────────────────────

// TODO ①: private final ObjectProvider<OrderCounter> counterProvider;
private final ObjectProvider<OrderCounter> counterProvider;

// TODO ②: @Autowired 생성자 작성
@Autowired
public CafeOrderService (ObjectProvider<OrderCounter> counterProvider) {
this.counterProvider = orderCounter;
}

public int processOrder(String itemName) {
System.out.println("[주문 처리] " + itemName);
// TODO ③: counterProvider.getObject()로 새 OrderCounter를 꺼내
// increment() 호출 후 getCount() 반환
return -1; // 완성 전 임시 반환값
OrderCounter orderCounter = counterProvider.getObject();
orderCounter.increment();
int count = orderCounter.getCount();
return count; // 완성 전 임시 반환값
}
}

Expand All @@ -174,23 +185,23 @@ static class CafeAppConfig { }
// main: TODO를 모두 완성한 후 아래 주석을 해제하고 실행해보세요.
// ──────────────────────────────────────────────────────────────────────
public static void main(String[] args) {
// AnnotationConfigApplicationContext ac =
// new AnnotationConfigApplicationContext(CafeAppConfig.class);
//
// // ── Part A 확인 ─────────────────────────────────────────────────
// CafeConnection conn = ac.getBean(CafeConnection.class);
// System.out.println("연결 상태: " + conn.isConnected()); // true 여야 함
// conn.sendOrder("아메리카노");
//
// // ── Part B 확인 ─────────────────────────────────────────────────
// CafeOrderService orderService = ac.getBean(CafeOrderService.class);
//
// int count1 = orderService.processOrder("카페라떼");
// int count2 = orderService.processOrder("에스프레소");
//
// System.out.println("주문 1 카운트: " + count1); // 1 이어야 함
// System.out.println("주문 2 카운트: " + count2); // 1 이어야 함 (새 프로토타입!)
//
// ac.close(); // @PreDestroy 호출 확인
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext(CafeAppConfig.class);

// ── Part A 확인 ─────────────────────────────────────────────────
CafeConnection conn = ac.getBean(CafeConnection.class);
System.out.println("연결 상태: " + conn.isConnected()); // true 여야 함
conn.sendOrder("아메리카노");

// ── Part B 확인 ─────────────────────────────────────────────────
CafeOrderService orderService = ac.getBean(CafeOrderService.class);

int count1 = orderService.processOrder("카페라떼");
int count2 = orderService.processOrder("에스프레소");

System.out.println("주문 1 카운트: " + count1); // 1 이어야 함
System.out.println("주문 2 카운트: " + count2); // 1 이어야 함 (새 프로토타입!)

ac.close(); // @PreDestroy 호출 확인
}
}
18 changes: 14 additions & 4 deletions src/week06/하성준/Problem1.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package week06.하성준;
package week06.solution;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
Expand Down Expand Up @@ -73,6 +73,7 @@ interface BookService {
// MemoryBookRepository에 @Component를 붙여서
// 컴포넌트 스캔 시 스프링이 자동으로 빈으로 등록하게 하세요.
// ──────────────────────────────────────────────────────────────────────
@Component
static class MemoryBookRepository implements BookRepository {
private final Map<Long, Book> store = new HashMap<>();

Expand All @@ -99,21 +100,28 @@ public Book findById(Long id) {
// 힌트: 생성자가 딱 1개면 @Autowired를 생략해도 자동 주입됩니다.
// 하지만 이번엔 명시적으로 붙여봅시다!
// ──────────────────────────────────────────────────────────────────────
@Component
static class BookServiceImpl implements BookService {

// TODO ②: private final BookRepository bookRepository;
private final BookRepository bookRepository;

// TODO ③: @Autowired 생성자 작성
@Autowired
public BookServiceImpl (BookRepository bookRepository) {
this.bookRepository = bookRepository;
}

@Override
public void register(Book book) {
// TODO ④: bookRepository.save(book) 호출
bookRepository.save(book);
}

@Override
public Book findBook(Long id) {
// TODO ④: return bookRepository.findById(id)
return null;
return bookRepository.findById(id);
}
}

Expand All @@ -127,12 +135,14 @@ public Book findBook(Long id) {
// 참고: @Bean 메서드는 작성하지 않아도 됩니다.
// @ComponentScan이 @Component 클래스들을 알아서 찾아 등록해줍니다.
// ──────────────────────────────────────────────────────────────────────
@ComponentScan
@Configuration
static class AutoAppConfig {
// 비어 있어도 괜찮습니다!
}

// ──────────────────────────────────────────────────────────────────────
// main: 먼저 실행해서 오류를 확인한 뒤, TODO를 채워서 고쳐보세요.
// main: TODO를 모두 완성한 후 아래 주석을 해제하고 실행해보세요.
// ──────────────────────────────────────────────────────────────────────
public static void main(String[] args) {
AnnotationConfigApplicationContext ac =
Expand All @@ -149,4 +159,4 @@ public static void main(String[] args) {

ac.close();
}
}
}
69 changes: 45 additions & 24 deletions src/week06/하성준/Problem2.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package week06.하성준;
package week06.solution;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
Expand Down Expand Up @@ -76,6 +76,7 @@ public void sendOrder(String item) {
// 빈 초기화 완료 직후 이 메서드가 자동으로 호출되도록
// @PostConstruct 애노테이션을 붙이세요.
// ──────────────────────────────────────────────────────────────────
@PostConstruct
public void init() {
System.out.println("[init] CafeConnection 초기화");
connect();
Expand All @@ -87,6 +88,7 @@ public void init() {
// 빈 소멸 직전에 이 메서드가 자동으로 호출되도록
// @PreDestroy 애노테이션을 붙이세요.
// ──────────────────────────────────────────────────────────────────
@PreDestroy
public void close() {
System.out.println("[close] CafeConnection 종료");
disconnect();
Expand All @@ -109,6 +111,7 @@ public void close() {
// OrderCounter가 스프링 컨테이너에 요청할 때마다 새로 생성되도록
// @Scope("prototype") 을 추가하세요.
// ──────────────────────────────────────────────────────────────────────
@Scope("prototype")
@Component
static class OrderCounter {
private int count = 0;
Expand Down Expand Up @@ -137,19 +140,37 @@ static class CafeOrderService {
// ──────────────────────────────────────────────────────────────────
// TODO B-2
// ──────────────────────────────────────────────────────────────────
// ① ObjectProvider<OrderCounter> 타입의 필드를 선언하세요.
// (필드명 예시: counterProvider)
//
// ② @Autowired 생성자를 작성해 ObjectProvider를 주입받으세요.
//
// ③ processOrder() 안에서:
// - counterProvider.getObject()로 새 OrderCounter를 꺼내세요.
// - increment()를 호출하세요.
// - getCount()를 반환하세요.
//
// 주의: getObject()를 호출할 때마다 새 프로토타입 빈이 생성됩니다.
// OrderCounter를 필드에 직접 @Autowired 주입받으면 어떻게 될지 생각해보세요.
// ──────────────────────────────────────────────────────────────────

// TODO ① 필드 선언: ObjectProvider<OrderCounter> 타입의 counterProvider를 선언하세요.
// TODO ①: private final ObjectProvider<OrderCounter> counterProvider;
private final ObjectProvider<OrderCounter> counterProvider;

// TODO ② 생성자: @Autowired를 붙인 생성자로 counterProvider를 주입받으세요.
// TODO ②: @Autowired 생성자 작성
@Autowired
public CafeOrderService (ObjectProvider<OrderCounter> counterProvider) {
this.counterProvider = orderCounter;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Assign injected provider parameter correctly

CafeOrderService's constructor assigns this.counterProvider from orderCounter, but that name is not defined in the constructor scope (the parameter is counterProvider). This causes a compile-time cannot find symbol error, so src cannot be built until the assignment uses the injected parameter.

Useful? React with 👍 / 👎.

}

public int processOrder(String itemName) {
System.out.println("[주문 처리] " + itemName);
// TODO ③ 구현: counterProvider.getObject()로 새 OrderCounter를 꺼내
// increment() 호출 후 getCount()를 반환하세요.
return -1; // TODO 완성 후 이 줄을 지우세요.
// TODO ③: counterProvider.getObject()로 새 OrderCounter를 꺼내
// increment() 호출 후 getCount() 반환
OrderCounter orderCounter = counterProvider.getObject();
orderCounter.increment();
int count = orderCounter.getCount();
return count; // 완성 전 임시 반환값
}
}

Expand All @@ -164,23 +185,23 @@ static class CafeAppConfig { }
// main: TODO를 모두 완성한 후 아래 주석을 해제하고 실행해보세요.
// ──────────────────────────────────────────────────────────────────────
public static void main(String[] args) {
// AnnotationConfigApplicationContext ac =
// new AnnotationConfigApplicationContext(CafeAppConfig.class);
//
// // ── Part A 확인 ─────────────────────────────────────────────────
// CafeConnection conn = ac.getBean(CafeConnection.class);
// System.out.println("연결 상태: " + conn.isConnected()); // true 여야 함
// conn.sendOrder("아메리카노");
//
// // ── Part B 확인 ─────────────────────────────────────────────────
// CafeOrderService orderService = ac.getBean(CafeOrderService.class);
//
// int count1 = orderService.processOrder("카페라떼");
// int count2 = orderService.processOrder("에스프레소");
//
// System.out.println("주문 1 카운트: " + count1); // 1 이어야 함
// System.out.println("주문 2 카운트: " + count2); // 1 이어야 함 (새 프로토타입!)
//
// ac.close(); // @PreDestroy 호출 확인
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext(CafeAppConfig.class);

// ── Part A 확인 ─────────────────────────────────────────────────
CafeConnection conn = ac.getBean(CafeConnection.class);
System.out.println("연결 상태: " + conn.isConnected()); // true 여야 함
conn.sendOrder("아메리카노");

// ── Part B 확인 ─────────────────────────────────────────────────
CafeOrderService orderService = ac.getBean(CafeOrderService.class);

int count1 = orderService.processOrder("카페라떼");
int count2 = orderService.processOrder("에스프레소");

System.out.println("주문 1 카운트: " + count1); // 1 이어야 함
System.out.println("주문 2 카운트: " + count2); // 1 이어야 함 (새 프로토타입!)

ac.close(); // @PreDestroy 호출 확인
}
}