λΉ μ€μ½ν
λΉ μ€μ½νλ λΉμ΄ μ‘΄μ¬ν μ μλ λ²μλ₯Ό λ»ν©λλ€.
μ€νλ§μ λ€μκ³Ό κ°μ λ€μν μ€μ½νλ₯Ό μ§μν©λλ€.
- μ±κΈν€(singleton) : κΈ°λ³Έ μ€μ½ν, μ€νλ§ μ»¨ν μ΄λμ μμκ³Ό μ’ λ£κΉμ§ μ μ§λλ κ°μ₯ λμ λ²μμ μ€μ½νμ λλ€.
- νλ‘ν νμ (prototype) : μ€νλ§ μ»¨ν μ΄λκ° νλ‘ν νμ λΉμ μμ±κ³Ό, μμ‘΄κ΄κ³ μ£Όμ κΉμ§λ§ κ΄μ¬νκ³ λλ κ΄λ¦¬νμ§ μλ λ§€μ° μ§¦μ λ²μμ μ€μ½νμ λλ€. (μ΄κΈ°ν λ©μλκΉμ§λ§ λΆλ¬μ£Όκ³ λλ κ΄λ¦¬νμ§ μκΈ°μ μ’ λ£ λ©μλλ νΈμΆλμ§ μμ΅λλ€.)
- μΉ κ΄λ ¨ μ€μ½ν :
- request : μΉ μμ²μ΄ λ€μ΄μ€κ³ λμ λκ°λ κΉμ§ μ μ§λλ μ€μ½νμ λλ€.
- session : μΉ μΈμ μ΄ μμ±λκ³ μ’ λ£λ λ κΉμ§ μ μ§λλ μ€μ½νμ λλ€.
- application : μΉμ μλΈλ¦Ώ 컨ν μ€νΈμ κ°μ λ²μλ‘ μ μ§λλ μ€μ½νμ λλ€.
λΉ μ€μ½νλ λ€μκ³Ό κ°μ΄ μ§μ ν μ μμ΅λλ€.
@Scope("prototype")
@Component
public class HelloBean {}
νλ‘ν νμ μ€μ½ν
μ±κΈν€ μ€μ½νμ λΉμ μ‘°ννλ©΄ μ€νλ§ μ»¨ν μ΄λλ νμ κ°μ μΈμ€ν΄μ€μ μ€νλ§ λΉμ λ°νν΄μ€λλ€.
λ°λ©΄ νλ‘ν νμ μ€μ½νλ₯Ό μ¬μ©νλ λΉμ μ‘°ν(getBean() λ±)νλ©΄, μ€νλ§ μ»¨ν μ΄λλ νμ μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό μμ±ν΄μ λ°νν©λλ€.
λ°ν μ΄ν μ€νλ§ μ»¨ν μ΄λλ μμ±λ νλ‘ν νμ λΉμ κ΄λ¦¬νμ§ μμΌλ―λ‘, @PreDestroy κ°μ μ’ λ£ λ©μλκ° νΈμΆλμ§ μμ΅λλ€.
μ±κΈν€μΌλ‘ μ μ§νκ³ μΆμ§λ μμΌλ, μμ‘΄κ΄κ³ μ£Όμ κ³Ό μ΄κΈ°ν λ©μλ νΈμΆμ΄ νμν κ²½μ°μ μ¬μ©ν©λλ€.
νλ‘ν νμ μ€μ½νμ μ±κΈν€ λΉμ ν¨κ» μ¬μ©ν μ μ£Όμμ
νλ‘ν νμ λΉμ μμ²νλ©΄ μ€νλ§ μ»¨ν μ΄λλ νμ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±ν΄μ λ°νν΄μ€λλ€.
κ·Έλ¬λ μ±κΈν€ λΉκ³Ό ν¨κ» μ¬μ©ν λλ μλν λλ‘ λμνμ§ μκΈ° λλ¬Έμ μ£Όμν μ μ΄ μμ΅λλ€.
νλ‘ν νμ λΉμ μ£Όμ λ°μ μ¬μ©νλ μ±κΈν€ λΉμ΄ μλ€κ³ μκ°ν΄λ³΄κ² μ΅λλ€.
μλμ κ°μ μν©μ λλ€.
μ΄λ€ μ¬μ©νμ ν΄λΉ μ±κΈν€ λΉμ νΈμΆνμ¬, λ΄λΆμ νλ‘ν νμ λΉμ νλλ₯Ό 0μμ 1λ‘ λ³κ²½νλ€κ³ κ°μ νκ² μ΅λλ€.
μ΄ μνμμ λλ€λ₯Έ μ¬μ©μκ° μ±κΈν€ λΉμ νΈμΆνμ¬ λ΄λΆμ νλ‘ν νμ λΉμ μνλ₯Ό μ‘°ννλ€κ³ νλ©΄, 0μ΄ μλλΌ μ΄μ μ¬μ©μμ μν΄ λ³κ²½λ 1μ΄ μ‘°νλ©λλ€.
μ°λ¦¬κ° μλν κ²μ μ‘°νν λλ§λ€ μλ‘μ΄ νλ‘ν νμ λΉμ΄ μμ±λμ΄ κ·Έκ²μ μ¬μ©νλ κ²μ΄μμκ²λλ€.
κ·Έλ¬λ μ±κΈν€ λΉμ μμ± μμ μ νλ‘ν νμ λΉμ νλ μ£Όμ λ°μ ν, κ·Έκ²μ μ¬λ¬ μ¬μ©μκ° κ³΅μ νλ―λ‘ νλ‘ν νμ λΉμ΄ κ³μ μμ±λμ§ μλ κ²μ λλ€.
κ·ΈλΌ μ΄ λ¬Έμ λ₯Ό μ΄λ»κ² ν΄κ²°ν μ μμκΉμ?
μ°λ¦¬κ° μνλ κ²μ μ±κΈν€ λΉμ μ±κΈν€μΌλ‘, νλ‘ν νμ λΉμ μ¬μ©ν λλ§λ€ μλ‘ μμ±λκ² νλ κ²μ λλ€.
ObjectProviderλ₯Ό μ¬μ©νμ¬ ν΄κ²°ν μ μμ΅λλ€.
ObjectProvider
μμ μ½λλ₯Ό ν΅ν΄ μ€λͺ νκ² μ΅λλ€.
@Scope("singleton")
public class ClientBean {
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
@Scope("prototype")
static class PrototypeBean {
private int count;
public void addCount() {
this.count ++;
}
public int getCount() {
return this.count;
}
}
}
μ€νν΄λ³΄λ©΄ prototypeBeanProviderμ getObject()λ₯Ό ν΅ν΄μ νμ μλ‘μ΄ νλ‘ν νμ λΉμ΄ μμ±λλ κ²μ νμΈν μ μμ΅λλ€.
ObjcetProviderμ getObjcet()λ₯Ό νΈμΆνλ©΄, μ€νλ§ μ»¨ν μ΄λλ₯Ό ν΅ν΄ ν΄λΉ νμ μ λΉμ μ°Ύμμ λ°νν΄μ€λλ€.
μ¦ ObjectProviderλ DL(Dependency Lookup)μ κΈ°λ₯μ μ 곡ν΄μ£Όλ κ²μ λλ€.
κ·Έλ¬λ ObjectProviderλ μ€νλ§μ μμ‘΄μ μ΄λΌλ λ¨μ μ΄ μμ΅λλ€.
JSR-330 Provider
μλ° νμ€μ μ¬μ©νλ λ°©λ²μ΄μ§λ§, μ΄λ₯Ό μ¬μ©νλ €λ©΄ λΌμ΄λΈλ¬λ¦¬λ₯Ό μΆκ°ν΄μ£Όμ΄μΌ νλ€λ λ¨μ μ΄ μμ΅λλ€.
implementation 'javax.inject:javax.inject:1'
@Scope("singleton")
public class ClientBean {
@Autowired
private Provider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
@Scope("prototype")
static class PrototypeBean {
private int count;
public void addCount() {
this.count ++;
}
public int getCount() {
return this.count;
}
}
}
μ¬μ© λ°©λ²μ κ°λ¨ν©λλ€.
(μ°Έκ³ λ‘ Providerλ lazy νΉμ optionalνκ² κ°μ Έμ¬ λ, circular dependencies(μν μ°Έμ‘°κ° λ°μν λ) λ±μ κ²½μ° μ¬μ©νλ©΄ μ’μ΅λλ€.)
ProxyMode
Provider λμ ProxyModeλ₯Ό μ¬μ©νμ¬ μ΄λ₯Ό ν΄κ²°ν μλ μμ΅λλ€.
proxyModeλ λ§ κ·Έλλ‘ νλ‘μλ₯Ό μ΄μ©νμ¬ ν΄κ²°νλλ°, ν΄λΉ νλ‘μ κ°μ²΄μ λ©μλλ₯Ό νΈμΆν λ μ€νλ§ μ»¨ν μ΄λμμ ν΄λΉ λΉμ μ‘°ννμ¬(getBean()) μ‘°νλ λΉμ λ‘μ§μ μμνλ λ°©μμ λλ€.
μμ μ½λλ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€.
@Scope("singleton")
public class ClientBean {
@Autowired
private PrototypeBean prototypeBean;
public int logic() {
prototypeBean.addCount(); // (1) μλ‘μ΄ PrototypeBean μμ±λ¨
int count = prototypeBean.getCount(); // (2) μλ‘μ΄ PrototypeBean μμ±λ¨
return count; // κ²°κ΅ 0μ΄ λ°ν
}
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
static class PrototypeBean {
private int count;
public void addCount() {
this.count ++;
}
public int getCount() {
return this.count;
}
}
}
(1)μμ prototypeBeanμ μ¬μ©νλ©°, μ΄λ ν΄λΉ λΉμ νλ‘ν νμ μ€μ½νλ₯Ό κ°μ§κΈ° λλ¬Έμ μλ‘ μμ±λ©λλ€.
(2)μμ λ§μ°¬κ°μ§λ‘ prototypeBeanμ μ¬μ©νλλ°, μ΄λμλ (1)μμ μμ±λ prototypeBeanμ΄ μλ, μλ‘μ΄ μμ²μ΄λ―λ‘ μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό μμ±νμ¬ λ°νν©λλ€.
μ΄λ‘ μΈν΄ κ²°κ΅ λ°νλλ κ°μ 0μ΄ λ©λλ€.
μ΄λ₯Ό ν΄κ²°νκΈ° μν΄μλ νλ²μ μμ²μΌλ‘ λ‘μ§μ λͺ¨λ μννλ λ°©λ² λ°μ μμ΅λλ€.
@Scope("singleton")
public class ClientBean {
@Autowired
private PrototypeBean prototypeBean;
public int logic() {
int count = prototypeBean.addAndGet();
return count;
}
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
static class PrototypeBean {
private int count;
public void addCount() {
this.count ++;
}
public int getCount() {
return this.count;
}
public int addAndGet() {
return ++this.count;
}
}
}
proxyModeλ μ μ© λμμ΄ ν΄λμ€λΌλ©΄ TARGET_CLASSλ₯Ό, μ μ© λμμ΄ μΈν°νμ΄μ€λΌλ©΄ INTERFACES λ₯Ό μ ννμλ©΄ λ©λλ€.
μ΄λ κ² νλ©΄ TARGET_CLASSλ CGLIBλ₯Ό ν΅ν΄, INTERFACESλ jdk λμ νλ‘μλ₯Ό ν΅ν΄ νλ‘μ κ°μ²΄λ₯Ό λ§λ€μ΄μ μ£Όμ νλ λ°©λ²μΌλ‘ ν΄κ²°ν©λλ€.
μΉ μ€μ½ν
- μΉ νκ²½μμλ§ λμν©λλ€.
- μ€νλ§μ΄ ν΄λΉ μ€μ½νμ μ’ λ£μμ κΉμ§ κ΄λ¦¬νλ―λ‘ μ’ λ£ λ©μλκ° νΈμΆλ©λλ€.
μ’ λ₯
- request : HTTP μμ² νλκ° λ€μ΄μ€κ³ λκ° λ κΉμ§ μ μ§λλ μ€μ½νμ λλ€. κ°κ°μ HTTP μμ²λ§λ€ λ³λμ λΉ μΈμ€ν΄μ€κ° μμ±λκ³ κ΄λ¦¬λ©λλ€.
- session : HTTP Sessionκ³Ό λμΌν μλͺ μ£ΌκΈ°λ₯Ό κ°μ§λ μ€μ½νμ λλ€.
- application : μλΈλ¦Ώ 컨ν μ€νΈ(ServletContext)μ λμΌν μλͺ μ£ΌκΈ°λ₯Ό κ°μ§λ μ€μ½νμ λλ€.
- websocket : μΉ μμΌκ³Ό λμΌν μλͺ μ£ΌκΈ°λ₯Ό κ°μ§λ μ€μ½νμ λλ€.
request μ€μ½νλ http μμ² λΉ λ‘κ·Έλ₯Ό λ¨κΈ΄λ€λμ§ λ±μ κΈ°λ₯μ μ¬μ©νμ€ μ μμ΅λλ€.
π Reference