AnnotationConfigApplicationContext ac =new AnnotationConfigApplicationContext(AppConfig.class);
GenericXmlApplicationContext acl = new GenericXmlApplicationContext("appConfig.xml");
@Test
@DisplayName("빈 설정 메타정보 확인")
void findApplicationBean(){
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
if( beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
System.out.println(beanDefinitionName +" "+ beanDefinition);
}
}
}
빈과 관련된 메타정보를 확인하기위해 beanDefinition 사용,
싱글톤 방식 (트레픽 관리를 위해 사용)
유저 여러명이 사이트에 방문했을 때, 객체를 여러개 생성하면 ex) MemberService memberService = new MemberService();
여러개의 인스턴스가 만들어져서, 컴퓨터가 맛탱이 가버릴 수 있다.
그럴때 사용하는 것이 싱글톤 방식인데 자바코드를 보며 스프링을 통해 어떻게 개선되었는지 한번 보자
public class SingletonTest(){
//스테틱 파이널로 내부에 객체를 생성(단일 객체를 생성하기 위함)
public static final SingletonTest instance = new SingletonTest();
//클래스 스테틱 메소드를 이용해 인스턴스를 반환할 수 있도록 진행
public static SingletonTest getInstance(){
return instance;
}
//생성자를 private로 하여, new 를 사용한 새로운 객체가 만들어 지는 것을 막음
private SingletonTest(){
}
}
위에 보이는 코드는 싱글톤 방식으로 여러개의 객체가 만들어지는 것을 막을 수 있다.
그럼 위 싱글톤 방식이 아무 문제가 없을까? 전혀아니다
그래서 스프링에선 스프링 컨테이너에서 단일 객체를 생성할 수 있도록 지원한다.
스프링Container에서 빈 이름과 빈객체를 구분해서 관리를 한다
@Test
@DisplayName("싱글톤 진짜 하나밖에 호출한돼 빈객체는? 와우")
void singleTonRealOne(){
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService = ac.getBean("memberService",MemberService.class);
MemberService memberService1 = ac.getBean("memberService",MemberService.class);
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService = " + memberService);
OrderService orderService = ac.getBean("orderService", OrderService.class);
OrderService orderService1 = ac.getBean("orderService", OrderService.class);
System.out.println("orderService1 = " + orderService1);
System.out.println("orderService2 = " + orderService);
assertThat(orderService).isSameAs(orderService1);
assertThat(memberService).isSameAs(memberService1);
}
}
여러개의 인스턴스 객체의 주소가 같다는 것을 확인할 수 있음
빈어노테이션 사용시 주의점. 실무에서 정말 많이 발생하는, stateful현상 유지로 인한 문제이다.
A라는 사용자가 접근하고 orderService를 이용한다고 했을 때 10000원 주문,
B라는 사용자는 20000원 주문 두 주문이 만약 겹친다면?
코드를 보며 생각해보자
public class StateFulServie{
int price;
public void orderService(String name, price)
this.price = price;
}
public int getPrice(){
return price;
}
}
import java.util.junit;
//테스트 코드 짜보기
public class TestCode{
@Test
@Displayname("스테이트풀 테스트")
void StatefulTest(){
ApplicationContext ac = new AnnotationConfigApplicationContext(StateFul.class);
StateFulService sfc = ac.getBean("statefus",stateFulService);
StateFulService sfc2 = ac.getBean("statefus",stateFulService);
sfc.order("손",10000); // 손은 만원을 주문
sfc2.order("민",20000); // 민은 2만원을 주문
Assertions.assertThat(sfc.getPrice).isEqualTo(10000); // fail
}
public class StateFul{
@bean
public stateFulService statefuls(){
return statefuls;
}
}
}
위테스트 코드를 실행하면 손은 만원을 주문했는데 2만원이 나온다 이게 어떻게된 일일까?
객체 주소가 같아 공동의 변수를 사용하게 됨으로써 , 주문이 겹치게 되면 치명적인 문제가 발생한다.
그럼 어떻게 개선해야할까 ?
public class StateFulServie{
public void orderService(String name,int price)
this.price = price;
}
public int getPrice(){
return price;
}
}
직접 메소드에 값을 넣고 꺼내면됨,