Springboot - Bean Scope(싱글톤, 프로토타입) ?

2019. 8. 17. 19:31Web/Spring

 

스프링에서 빈을 생성할 때, 기본 전략은 모든 빈이 싱글톤으로 생성된다. 즉, 어디에서든지 빈을 주입받는 다면 동일한 빈을 주입받는 것을 보장한다. 하지만 필요에 따라서 빈 주입마다 새로운 빈을 생성해야할 필요가 있을 경우도 있다. 이럴 경우에는 빈 생성시 Scope를 prototype으로 주면 빈 주입마다 새로운 인스턴스가 생성되는 것을 보장한다. 하지만 프로토타입 빈을 사용할 경우 주의해야 할 상황이 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
public class ABean {
    
    @Autowired
    private BBean b;
 
    public void bMethod() {
        b.print();
    }
    
}
 
@Component
@Scope("prototype")
public class BBean {
    
    public void print() {
        System.out.println("BBean !");
    }
}
cs

 

이런식으로 사용한다면 어떻게 될까? 이것은 사실 프로토타입을 쓰나마나이다. 싱글톤으로 생성된 A빈에 프로토타입 B빈을 주입해봤자 A빈은 더이상 생성되지 않기 때문에 항상 동일한 B빈을 사용하게 되는 것이다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@Component
public class ABean {
    
    @Autowired
    private BBean b;
    
    public void print() {
        System.out.println(b.hashCode());
    }
    
}
 
@Component
@Scope("prototype")
public class BBean {
    
}
 
@Component
public class CBean {
    
    @Autowired
    private ABean a;
    
    public void print() {
        a.print();
    }
}
 
@Component
public class DBean {
    
    @Autowired
    private ABean a;
    
    public void print() {
        a.print();
    }
}
 
@SpringBootApplication
public class CircularReferenceApplication implements CommandLineRunner{
    
    @Autowired private CBean c;
    @Autowired private DBean d;
 
    public static void main(String[] args) {
        SpringApplication.run(CircularReferenceApplication.class, args);
    }
 
    @Override
    public void run(String... args) throws Exception {
        c.print();
        d.print();
    }
    
}
cs

 

위 코드를 실행시켜보자. 프로토타입 빈으로 등록된 B빈이지만 항상 어디서든 동일한 해시코드를 반환한다. 즉, 프로토타입빈을 사용하기 위해서는 아래와 같이 사용하자.

 

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
@Service
public class BeanUtil implements ApplicationContextAware {
 
    private static ApplicationContext context;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
 
    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }
}
 
@Component
public class ABean {
    
    public void print() {
        BBean b = BeanUtil.getBean(BBean.class);
        System.out.println(b.hashCode());
    }
    
}
 
cs

 

ApplicationContext 객체에서 직접 빈을 가져와서 메소드 내부에서 사용하도록 하자. 이제는 매번 다른 B빈의 해시코드를 반환할 것이다.

 

2019/02/25 - [Web/Spring] - Spring - ApplicationContext,ApplicationContextAware, 빈이 아닌 객체에 빈주입할때!

 

Spring - ApplicationContext,ApplicationContextAware, 빈이 아닌 객체에 빈주입할때!

Spring - ApplicationContext,ApplicationContextAware, 빈이 아닌 객체에 빈주입할때! @Autuwired,@Inject 등의 어노테이션으로 의존주입을 하기 위해서는 해당 객체가 빈으로 등록되어 있어야만 가능하다. 사실..

coding-start.tistory.com