[Spring] ๋น์ Scope - ์ฑ๊ธํค๊ณผ ํ๋กํ ํ์
๋น์ ๋ฑ๋กํ ๋ ์๋ฌด๋ฐ ์ค์ ์ ํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ๋น์ ์ฑ๊ธํค scope์ ๊ฐ๋๋ค.
์ฑ๊ธํค scope์ด๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ๊ฑธ์ณ ํด๋น ๋น์ ์ธ์คํด์ค๋ฅผ ์ค์ง ํ๋๋ง ์์ฑํด์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
1. Singleton Scope
Single, Proto ํด๋์ค๋ฅผ ์๋ก ๋ง๋ค๊ณ @Component๋ฅผ ๋ถ์ฌ ๋น์ผ๋ก ๋ฑ๋กํ๋ค.
Single.java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Single {
@Autowired
private Proto proto;
public Proto getProto() {
return proto;
}
}
|
cs |
Proto.java
1
2
3
4
5
|
import org.springframework.stereotype.Component;
@Component
public class Proto {
}
|
cs |
Single์ Proto๋ฅผ ์ฃผ์ ํ๋ค.
AppRunner.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
Single single;
@Autowired
Proto proto;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(proto);
System.out.println(single.getProto());
}
}
|
cs |
ApplicationRunner๋ฅผ ๋ง๋ค๊ณ Single๊ณผ Proto๋ฅผ ์ฃผ์ ๋ฐ์ runner๊ฐ ์ฃผ์ ๋ฐ์ Proto์ Single์์ ๊ฐ์ ธ์จ Proto๋ฅผ ์ถ๋ ฅํด๋ณด์.
์คํ ๊ฒฐ๊ณผ
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ก ๋ ๋ ํผ๋ฐ์ค๊ฐ ํ๋์ ๋์ผํ ์ธ์คํด์ค์ธ๊ฒ์ ํ์ธํ ์ ์๋ค.
Proto๋ฅผ ๋น์ผ๋ก ๋ฑ๋กํ ๋ scope์ ๋ฐ๋ก ์ค์ ํด์ฃผ์ง ์์์ผ๋ฏ๋ก ์ฑ๊ธํค scope์ ๊ฐ๊ณ , ์ดํ๋ฆฌ์ผ์ด์ ์ด ์์ํ ๋ ์์ฑ๋๋ ํ๋์ ์ธ์คํด์ค๋ฅผ ์ฐ๊ธฐ ๋๋ฌธ์ด๋ค.
1) ์ฑ๊ธํค ๋น ์ฌ์ฉ์ ์ฃผ์ํ ์
- ํ๋กํผํฐ ๊ณต์
์ฑ๊ธํค ๊ฐ์ฒด์ ํ๋กํผํฐ๋ thread-safeํ๋ค๊ณ ๋ณด์ฅํ ์ ์๋ค.
๋ฉํฐ์ฐ๋ ๋ ํ๊ฒฝ์์ ์ฑ๊ธํค ๊ฐ์ฒด์ ํ๋กํผํฐ๋ ์ฌ๋ฌ ์ฐ๋ ๋์ ์ํด ๋ฐ๋ ์ ์๋๋ฐ
๊ฐ๋ น ์ฐ๋ ๋ A์์ ํ๋กํผํฐ ๊ฐ์ x๋ก ๋ฐ๊พธ๊ณ ์ถ๋ ฅํ๋ ๊ณผ์ ์์ ์ฐ๋ ๋ B๊ฐ ํ๋กํผํฐ ๊ฐ์ y๋ก ๋ฐ๊พธ๋ฉด ์ฐ๋ ๋ A ์ ์ฅ์์๋ ์์์น ๋ชปํ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ์๋ ์๋๊ฒ์ด๋ค.
- Application ์ด๊ธฐ ๊ตฌ๋ ์ ์ธ์คํด์ค ์์ฑ
์ฑ๊ธํค ๋น์ ๋ชจ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ดํ๋ฆฌ์ผ์ด์ ๊ตฌ๋ ์ ์์ฑ๋๋ฏ๋ก ์ฑ๊ธํค ๋น์ด ๋ง์ ์๋ก ๊ตฌ๋ ์๊ฐ์ด ์ฆ๊ฐํ ์ ์๋ค.
2. Prototype Scope
๋น์ scope ์ค์ ์ @Scope ์ ๋ ธํ ์ด์ ์ ์ค์ ํ ์ ์๋ค.
ํ๋กํ ํ์ scope์ผ๋ก ์ค์ ํ๋ ค๋ฉด @Scope("prototype")๊ณผ ๊ฐ์ด ๋ฌธ์์ด๋ก ์ง์ ํด์ค๋ค.
Proto.java
1
2
3
4
5
6
|
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component @Scope("prototype")
public class Proto {
}
|
cs |
Proto๋ง @Scope๋ฅผ ๋ถ์ฌ scope๋ฅผ ํ๋กํ ํ์ ์ผ๋ก ์ค์ ํ๋ค.
AppRunner.java
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
|
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext ctx;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Proto:");
System.out.println(ctx.getBean(Proto.class));
System.out.println(ctx.getBean(Proto.class));
System.out.println(ctx.getBean(Proto.class));
System.out.println("Single:");
System.out.println(ctx.getBean(Single.class));
System.out.println(ctx.getBean(Single.class));
System.out.println(ctx.getBean(Single.class));
}
}
|
cs |
Runner์์ ApplicationContext๋ฅผ ์ฃผ์ ๋ฐ๊ณ Proto์ Single ๋น์ ์ธ๋ฒ์ฉ ์ถ๋ ฅํด๋ณด์.
์คํ ๊ฒฐ๊ณผ
Proto๋ ๋ชจ๋ ๋ค๋ฅธ ์ธ์คํด์ค์ด๊ณ Single์ ๋ชจ๋ ๊ฐ์ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
ํ๋กํ ํ์ scope๋ ์ฑ๊ธํค scope๊ณผ ๋ฌ๋ฆฌ IoC์์ ๋น์ ๋ฐ์์ฌ๋๋ง๋ค ๋งค๋ฒ ์ธ์คํด์ค๋ฅผ ์๋ก ์์ฑํ๋ค.
์ด๋ ๊ฒ ๋น์ scope๋ฅผ ๊ฐ๋จํ๊ฒ ๊ด๋ฆฌํด์ค ์ ์๋ ๊ฒ์ด spring์ ์ฅ์ ์ด๋ค.
๊ทธ๋ฌ๋ ํ๋กํ ํ์ ๋น๊ณผ ์ฑ๊ธํค ๋น์ ์์ด์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
3. ํ๋กํ ํ์ ๋น๊ณผ ์ฑ๊ธํค ๋น์ ์์ด์ ์ฌ์ฉ
1) ํ๋กํ ํ์ ๋น์์ ์ฑ๊ธํค ๋น์ ์ฐธ์กฐํ๋ ๊ฒฝ์ฐ
์ด ๊ฒฝ์ฐ๋ ์๋ฌด ๋ฌธ์ ๊ฐ ์๋ค.
์๋์ ๊ฐ์ด ํ๋กํ ํ์ ๋น Proto์์ ์ฑ๊ธํค ๋น Single์ ์ฌ์ฉํ๋ค๊ณ ๊ฐ์ ํด๋ณด์.
1
2
3
4
5
6
7
8
9
10
|
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component @Scope("prototype")
public class Proto {
@Autowired
Single single;
}
|
cs |
ํ๋กํ ํ์ ๋น์ ์ธ์คํด์ค๋ ๊ณ์ ์์ฑ๋๊ณ ์ฃผ์ ๋ฐ๋ ์ฑ๊ธํค ๋น์ ๊ณ์ ๋์ผํ ํ๋์ ์ธ์คํด์ค์ผ๊ฒ์ด๋ค.
์ด๋ฌํ ๊ฒฐ๊ณผ๋ ๊ฐ๋ฐ์์ ๊ธฐ๋, ์๋์์ ๋ฒ์ด๋์ง ์๋๋ค.
2) ์ฑ๊ธํค ๋น์์ ํ๋กํ ํ์ ๋น์ ์ฐธ์กฐํ๋ ๊ฒฝ์ฐ
์ด ๊ฒฝ์ฐ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
์ฑ๊ธํค ๋น์ ์ธ์คํด์ค๋ ๋จ ํ๋ฒ๋ง ์์ฑ๋๊ณ ๊ทธ ๋ ํ๋กํ ํ์ ๋น์ ์ฃผ์ ๋ ์ด๋ฏธ ์๋ฃ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ฑ๊ธํค ๋น์ ์ฌ์ฉํ ๋ ์ฃผ์ ๋ฐ์ ํ๋กํ ํ์ ๋น์ด ๋ณ๊ฒฝ(์ ๋ฐ์ดํธ) ๋์ง ์๋๋ค.
AppRunner.java
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
|
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext ctx;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Proto:");
System.out.println(ctx.getBean(Proto.class));
System.out.println(ctx.getBean(Proto.class));
System.out.println(ctx.getBean(Proto.class));
System.out.println("Single:");
System.out.println(ctx.getBean(Single.class));
System.out.println(ctx.getBean(Single.class));
System.out.println(ctx.getBean(Single.class));
System.out.println("Proto by Single:");
System.out.println(ctx.getBean(Single.class).getProto());
System.out.println(ctx.getBean(Single.class).getProto());
System.out.println(ctx.getBean(Single.class).getProto());
}
}
|
cs |
์ฑ๊ธํค ๋น์ธ Single์ ํตํด ํ๋กํ ํ์ ๋น Proto๋ฅผ ๊ฐ์ ธ์์ ์ถ๋ ฅํด๋ณด์.
์คํ ๊ฒฐ๊ณผ
์์ ๊ฐ์ด ์ฑ๊ธํค ๋น Single ์์ Proto๋ ํ๋กํ ํ์ ์ธ๋ฐ๋ ๋ถ๊ตฌํ๊ณ ์ฃผ์ ๋๊ณ ๋์ ์ธ์คํด์ค๊ฐ ์๋ก ์์ฑ๋์ง ์๋๋ค.
์ด๋ ๊ฒ ์ฑ๊ธํค ๋น์์ ํ๋กํ ํ์ ๋น์ ์ฐธ์กฐํ ๋๋ ๋ค์ ๋ฐฉ๋ฒ์ผ๋ก ์ธ์คํด์ค๊ฐ ์ ๋ฐ์ดํธ๋๋๋ก ํ ์ ์๋ค.
4. ์ ๋ฐ์ดํธ ๋ฌธ์ ํด๊ฒฐ ๋ฐฉ๋ฒ
1) ๋ฐฉ๋ฒ 1 - proxyMode ์ค์
ํ๋กํ ํ์ ๋น์ @Scope ์ ๋ ธํ ์ด์ ์ proxyMode ์์ฑ์ ์ค์ ํด์ค๋ค.
Proto.java
1
2
3
4
5
6
7
|
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
@Component @Scope(scopeName = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Proto {
}
|
cs |
proxyMode ์์ฑ์ ์ค์ ํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ๊ฐ์ scopedProxyMode.DEFAULT์ด๋ค.
DEFAULT๋ proxy๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๋ ์ต์ ์ด๊ณ proxy๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํด๋์ค์ธ ๊ฒฝ์ฐ TARGET_CLASS, ์ธํฐํ์ด์ค์ผ ๊ฒฝ์ฐ INTERFACES๋ก ์ค์ ํ๋ค.
- scopedProxyMode.DEFAULT : Proxy๋ฅผ ์ฌ์ฉํ์ง ์์
- scopedProxyMode.TARGET_CLASS : Proxy๋ฅผ ์ฌ์ฉํจ(ํด๋์ค)
- scopedProxyMode.INTERFACES : Proxy๋ฅผ ์ฌ์ฉํจ(์ธํฐํ์ด์ค)
์คํ ๊ฒฐ๊ณผ
Proxy๋ฅผ ์ด๋ค๋ ๊ฒ์ ๋์ ๋น์ proxy๋ก ๊ฐ์ผ๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๊ฒ ํจ์ผ๋ก์จ ํด๋น ๋น์ ์ฌ์ฉํ๋ ๋น๋ค์ด ํ๋ก์๋ก ๊ฐ์ผ ๋น์ ์ฌ์ฉํ๊ฒ ํ๋ค.
์ฑ๊ธํค ๋น์ด ํ๋กํ ํ์ ๋น์ ์ฌ์ฉํ ๋ proxy๋ก ๊ฐ์ธ์ผํ๋ ์ด์ ๋, ํ๋กํ ํ์ ๋น์ ์ง์ ์ฐธ์กฐํ๋ฉด ์ธ์คํด์ค๋ฅผ ์๋ก ์์ฑํด์ค ์ฌ์ง๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ฆ ๋งค๋ฒ ์ธ์คํด์ค๋ฅผ ์๋ก ์์ฑํด์ค ์ ์๋ ํ๋ก์๋ก ๊ฐ์ธ์ฃผ๋ ๊ฒ์ด๋ค.
์ฐธ๊ณ ๋ก ์๋ JDK ์์ ์๋ dynamic proxy๋ ์ธํฐํ์ด์ค์ ํ๋ก์๋ง ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ ํด๋์ค์ ํ๋ก์๋ ์จ๋ ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค.
์์ ์ฝ๋์ ๊ฐ์ด ScopedProxyMode.TARGET_CLASS๋ผ๊ณ ์ค์ ํ๋ ๊ฒ์ ํ๊ฒ ํด๋์ค์ proxy๋ฅผ ๋ง๋ค๋ผ๊ณ ์๋ ค์ฃผ๋ ๊ฒ์ด๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ์ค์ ์ธ์คํด์ค๋ฅผ ๊ฐ์ธ๋ ํ๋ก์ ์ธ์คํด์ค๊ฐ ์์ฑ๋๊ณ , ์ด ํ๋ก์ ์ธ์คํด์ค๊ฐ ๋น์ผ๋ก ๋ฑ๋ก๋๋ค.
๋ฐ๋ผ์ ์ค์ง์ ์ผ๋ก ์ฃผ์ ๋๋ ๋น์ ํ๋ก์ ๋น์ด๋ค.
ํ๋ก์ ๋น๋ ์๋ณธ ํ๋กํ ํ์ ๋น์ ์์ํด์ ๋ง๋ค๊ธฐ ๋๋ฌธ์ ํ์ ์ ๋์ผํ๋ค.
ํ์ ์ด ๊ฐ์ผ๋ฏ๋ก ๋ฌธ์ ์์ด ์ฃผ์ ๋ ์ ์๋ค.
2) ๋ฐฉ๋ฒ 2 - ObjectProvider ์ฌ์ฉ
์ด ๋ฐฉ๋ฒ์ ๋น ์ค์ ์ด ์๋ ์ฝ๋๋ฅผ ์์ ํด์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ด๋ค.
์์์ ์ค์ ํ proxyMode๋ฅผ ์๋ณตํ๊ณ Single.java๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ๋ค.
Single.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Single {
@Autowired
private ObjectProvider<Proto> proto;
public Proto getProto() {
return proto.getIfAvailable();
}
}
|
cs |
ํ๋กํ ํ์ ๋น์ ์ฃผ์ ๋ฐ๋ ํ๋์ ํ์ ์ ObjectProvider๋ก ๊ฐ์ธ๊ณ getter์์ getIfAvailable()๋ก ๋ฆฌํดํ๋๋ก ํ๋ค.
์คํ ๊ฒฐ๊ณผ
์ด ๋ฐฉ๋ฒ์ ์ฝ๋ ์์ ์ด ํ์ํ๋ฉฐ spring ์ฝ๋๊ฐ ๋ค์ด๊ฐ๊ธฐ ๋๋ฌธ์ ์๋ฐ ๊ฐ์ฒด๊ฐ POJO ์คํ์ผ์์ ๋ฒ์ด๋๊ฒ ๋๋ค๋ ํน์ง์ด ์๋ค.
์ด๋ค ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ , ์ด๋ ๊ฒ Scope์ด ๋์ ๋น(์ฑ๊ธํค ๋น)์์ scope์ด ์งง์ ๋น(ํ๋กํ ํ์ ๋น)์ ์ฃผ์ ๋ฐ์ ๋๋ ์ฃผ์๊ฐ ํ์ํ๋ค๋ ์ ์ ๋ฐ๋์ ์์๋์.
References
์ธํ๋ฐ - ๋ฐฑ๊ธฐ์ ๋์ ์คํ๋ง ํ๋ ์์ํฌ ํต์ฌ ๊ธฐ์
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] EnvironmentCapable - Property ์ฌ์ฉํ๊ธฐ (0) | 2020.03.04 |
---|---|
[Spring] EnvironmentCapable - Profile ์ฌ์ฉํ๊ธฐ (0) | 2020.03.04 |
[Spring] Component Scan๊ณผ Function์ ์ฌ์ฉํ ๋น ๋ฑ๋ก ๋ฐฉ๋ฒ (1) | 2020.03.02 |
[Spring] @Autowired ๋์ ์๋ฆฌ - BeanPostProcessor (0) | 2020.03.01 |
[Spring] @Autowired์ ๋ค์ํ ์ฌ์ฉ ๋ฐฉ๋ฒ - required, Primary, Qualifier (0) | 2020.03.01 |
๋๊ธ