๐ฏ ๋ชฉํ : Bean Scope์ ์ดํด
public class PrototypeTest {
@Test
void test() {
AnnotationConfigApplicationContext ac
= new AnnotationConfigApplicationContext(ProtoTypeBean.class);
System.out.println("find prototypeBean1");
ProtoTypeBean bean1 = ac.getBean(ProtoTypeBean.class);
System.out.println("find prototypeBean2");
ProtoTypeBean bean2 = ac.getBean(ProtoTypeBean.class);
System.out.println("bean1 = " + bean1);
System.out.println("bean2 = " + bean2);
Assertions.assertThat(bean1).isNotSameAs(bean2);
ac.close();
/* prototype๋ ์ปจํ
์ด๋๊ฐ ์ข
๋ฃ ๋๋๋ผ๋ ์ปจํ
์ด๋์ ๊ด๋ฆฌ ๋น์ด ์๋๊ธฐ๋๋ฌธ์
* destroy๊ฐ ํธ์ถ ๋์ง ์๋๋ค
* ์ฆ ์์ฑ๊ณผ ์์กด๊ด๊ณ ์ฃผ์
๊ทธ๋ฆฌ๊ณ ์ด๊ธฐํ ๊น์ง๋ง ๊ด์ฌํ๋ค.*/
}
@Scope("prototype")
static class ProtoTypeBean {
@PostConstruct
public void init() {
System.out.println("SingletonBean.init");
}
@PreDestroy
public void destroy() {
System.out.println("SingletonBean.destroy");
}
}
}
// ์ถ๋ ฅ๊ฐ
find prototypeBean1
PrototypeBean.init
find prototypeBean2
PrototypeBean.init
bean1 = hello.core.scope.PrototypeTest$ProtoTypeBean@55493582
bean2 = hello.core.scope.PrototypeTest$ProtoTypeBean@1a20270e
public class SingletonWithPrototypeTest1 {
// TEST1
@Test
void singletonClientUsePrototype() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class, ClientBean.class);
ClientBean bean1 = ac.getBean(ClientBean.class);
int count1 = bean1.logic();
assertThat(count1).isEqualTo(1);
ClientBean bean2 = ac.getBean(ClientBean.class);
int count2 = bean2.logic();
assertThat(count2).isEqualTo(2);
// ์ถ๋ ฅ๊ฐ
// PrototypeBean.inithello.core.scope.SingletonWithPrototypeTest1$PrototypeBean@1e097d59
}
// TEST2
@Test
void singletonClientUseProviderPrototype() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class, ClientBean2.class);
ClientBean2 bean1 = ac.getBean(ClientBean2.class);
int count1 = bean1.logic();
assertThat(count1).isEqualTo(1);
ClientBean2 bean2 = ac.getBean(ClientBean2.class);
int count2 = bean2.logic();
assertThat(count2).isEqualTo(1);
// ์ถ๋ ฅ๊ฐ
//PrototypeBean.inithello.core.scope.SingletonWithPrototypeTest1$PrototypeBean@531f4093
//PrototypeBean.inithello.core.scope.SingletonWithPrototypeTest1$PrototypeBean@373ebf74
}
@Scope("singleton")
static class ClientBean {
private final PrototypeBean prototypeBean;
@Autowired
public ClientBean(PrototypeBean prototypeBean) {
this.prototypeBean = prototypeBean;
}
public int logic() {
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
@Scope("singleton")
static class ClientBean2 {
private final Provider<PrototypeBean> prototypeBeanProvider;
@Autowired
ClientBean2(Provider<PrototypeBean> prototypeBeanProvider) {
this.prototypeBeanProvider = prototypeBeanProvider;
}
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.get();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
@Scope("prototype")
static class PrototypeBean {
private int count = 0;
public void addCount() {
count++;
}
public int getCount() {
return count;
}
@PostConstruct
public void init() {
System.out.println("PrototypeBean.init"+this);
}
@PreDestroy
public void destory() {
System.out.println("PrototypeBean.destory");
}
}
}
// MyLogger.java
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
/* ๊ฐ์ง ํ๋ก์ ํด๋์ค๋ฅผ ๋ง๋ค์ด ๋๊ณ ์ฃผ์
ํด์ค๋ค*/
public class MyLogger {
private String uuid;
private String requestURL;
public void setRequestURL(String requestURL) {
this.requestURL = requestURL;
}
public void log(String message) {
System.out.println("["+uuid+"]"+"["+requestURL+"]"+message);
}
@PostConstruct
public void init() {
uuid = UUID.randomUUID().toString();
System.out.println("["+uuid+"]"+" request scop bean create "+this);
}
@PreDestroy
public void close() {
System.out.println("["+uuid+"]"+" request scop bean close "+this);
}
}
// LogDemoController.java
@Controller
@RequiredArgsConstructor
public class LogDemoController {
private final LogDemoService logDemoService;
/* ์๋ฒ๊ฐ ์คํ๋ ๋ request scope ๋น์ ์์ฑ๋ ์๊ฐ ์๋ค
* Provider๋ฅผ ํ์ฉํด์ ํด๊ฒฐ ํด์ผํ๋ค
* ํ์ง๋ง MyLogger์์ proxyMode๋ฅผ ์ฌ์ฉํ๋ฉด Provider๋ฅผ ์ฌ์ฉํ ํ์๋ ์์ด์ง๋ค*/
private final MyLogger myLogger;
@RequestMapping("/log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request) {
String requestURL = request.getRequestURL().toString();
// MyLogger myLogger = myLoggerProvider.getObject();
/* ์ฃผ์
ํด์ฃผ๋ ๊ฐ์ง ํ๋ก์ ํด๋์ค๋ฅผ ํ์ธํด๋ณด์ */
System.out.println("myLogger = " + myLogger.getClass());
myLogger.setRequestURL(requestURL);
myLogger.log("Controller Test");
logDemoService.logic("testId");
return "OK";
}
}
//LogDemoService.java
@Service
@RequiredArgsConstructor
public class LogDemoService {
/* ์๋ฒ๊ฐ ์คํ๋ ๋ request scope ๋น์ ์์ฑ๋ ์๊ฐ ์๋ค
* Provider๋ฅผ ํ์ฉํด์ ํด๊ฒฐ ํด์ผํ๋ค
* ํ์ง๋ง MyLogger์์ proxyMode๋ฅผ ์ฌ์ฉํ๋ฉด Provider๋ฅผ ์ฌ์ฉํ ํ์๋ ์์ด์ง๋ค*/
// private final ObjectProvider<MyLogger> myLoggerProvider;
private final MyLogger myLogger;
public void logic(String testId) {
// MyLogger myLogger = myLoggerProvider.getObject();
myLogger.log("Service Id = " + testId);
}
}
Error creating bean with name 'myLogger': Scope 'request' is not active for the
current thread; consider defining a scoped proxy for this bean if you intend to
refer to it from a singleton;
System.out.println("myLogger = " + myLogger.getClass());
// ์ถ๋ ฅ๊ฐ
// myLogger = class hello.core.common.MyLogger$$EnhancerBySpringCGLIB$$b68b726d