
Product(추상), Beverage, Bread, ShoppingCartShoppingCart는 내부에 List<Product>를 보유하고 addItem()으로 담는 구조. | 스코프 | 의미 |
|---|---|
| singleton | 컨테이너당 인스턴스 1개 공유(기본값) |
| prototype | getBean() 호출 시마다 새 인스턴스 |
| request | HTTP 요청마다 1개(웹 컨텍스트 한정) |
| session | HTTP 세션마다 1개(웹 컨텍스트 한정) |
@Configuration
public class ContextConfiguration {
@Bean public Product carpBread() { return new Bread("붕어빵", 1000, new Date()); }
@Bean public Product milk() { return new Beverage("딸기우유", 1500, 500); }
@Bean
@Scope("singleton") // 기본값(명시 가능)
public ShoppingCart cart() { return new ShoppingCart(); }
// @Scope("prototype") 로 전환하면 호출할 때마다 새 카트
}
singleton cart: 서로 다른 손님이 cart를 꺼내도 같은 인스턴스(hashCode 동일).
prototype cart: getBean("cart") 호출마다 새 인스턴스(hashCode 상이).
시나리오: 손님1이 붕어빵·딸기우유 담고, 손님2가 물 담을 때
public class Owner {
public void openShop() { System.out.println("문 오픈"); }
public void closeShop() { System.out.println("문 클로즈"); }
}
@Configuration
public class ContextConfiguration {
@Bean(initMethod="openShop", destroyMethod="closeShop")
public Owner owner() { return new Owner(); }
}
// 종료 시 destroy 호출을 보려면 컨테이너 close 필요
((AnnotationConfigApplicationContext) ctx).close();
@Component
public class Owner {
@PostConstruct public void openShop() { /* init */ }
@PreDestroy public void closeShop() { /* destroy */ }
}
<bean id="owner" class="...Owner"
init-method="openShop" destroy-method="closeShop"/>
# product-info.properties
bread.carpbread.name=붕어빵
bread.carpbread.price=1000
beverage.milk.name=딸기우유
beverage.milk.price=1500
beverage.milk.capacity=500
@Configuration
@PropertySource("section03/properties/subsection01/properties/product-info.properties")
public class ContextConfiguration {
@Value("${bread.carpbread.name:팥붕어빵}") private String carpBreadName;
@Value("${bread.carpbread.price:0}") private int carpBreadPrice;
@Bean
public Product carpBread() {
return new Bread(carpBreadName, carpBreadPrice, new Date());
}
@Bean
public Product milk(
@Value("${beverage.milk.name:}") String name,
@Value("${beverage.milk.price:0}") int price,
@Value("${beverage.milk.capacity:0}") int capacity) {
return new Beverage(name, price, capacity);
}
}
${key:기본값} 형태로 치환자(placeholder) 사용, 필드·파라미터에 주입 가능. # message_ko_KR.properties
error.404=페이지를 찾을 수 없습니다!
error.500=개발자의 잘못입니다. 개발자는 누구? {0} 입니다. 현재시간 {1}
# message_en_US.properties
error.404=Page Not Found!!
error.500=something wrong! The developer''s fault. who is devloper? It''s {0} at {1}
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
var ms = new ReloadableResourceBundleMessageSource();
ms.setBasename("section03/properties/subsection02/i18n/message");
ms.setCacheSeconds(10);
ms.setDefaultEncoding("UTF-8");
return ms;
}
String m404 = ctx.getMessage("error.404", null, Locale.KOREA);
String m500 = ctx.getMessage("error.500", new Object[]{"여러분", new Date()}, Locale.KOREA);
getMessage(code, args, locale)로 코드·인자·로케일을 전달해 메시지를 조회. ${key:default} 로 안전 주입.MessageSource와 로케일로 오류/알림 메시지 관리.