Spring / ์คํ๋ง ๋น Life-cycle callback
by rlaehddnd0422๋น ์๋ช ์ฃผ๊ธฐ ์ฝ๋ฐฑ ์์
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปค๋ฅ์ ํ์ด๋, ๋คํธ์ํฌ ์์ผ์ฒ๋ผ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์ ์ ํ์ํ ์ฐ๊ฒฐ์ ๋ฏธ๋ฆฌ ํด๋๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ข ๋ฃ ์์ ์ ์ฐ๊ฒฐ์ ๋ชจ๋ ์ข ๋ฃํ๋ ์์ ์ ์งํํ๋ ค๋ฉด, ๊ฐ์ฒด์ ์ด๊ธฐํ์ ์ข ๋ฃ ์์ ์ด ํ์ํ๋ค.
์๋ฅผ๋ค์ด ์ธ๋ถ ๋คํธ์ํฌ์ ๋ฏธ๋ฆฌ ์ฐ๊ฒฐํ๋ ๊ฐ์ฒด๋ฅผ ํ๋ ์์ฑํ๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์ค์ ์ฐ๊ฒฐ์ ์๋๊ณ ๋จ์ํ ๋ฌธ์๋ง ์ถ๋ ฅํ๋๋ก ํ๋ค.
์ด NetworkClient๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์ ์ connect()๋ฅผ ์ถํด์ ์ฐ๊ฒฐ์ ๋งบ์ด๋์ด์ผ ํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ข ๋ฃ๋๋ฉด disconnect()๋ฅผ ํธ์ถํด์ ์ฐ๊ฒฐ์ ๋์ด์ผ ํ๋ค.
package hello.core.lifecycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class NetworkClient {
private String url;
public NetworkClient()
{
System.out.println("์์ฑ์ ํธ์ถ, url = " + url);
connect();
call("์ด๊ธฐํ ์๋ฃ");
}
public void setUrl(String url) {
this.url = url;
}
public void connect()
{
System.out.println("connect : " + url);
}
public void call(String message)
{
System.out.println("call: " + url + " message : " + message);
}
// ์๋น์ค ์ข
๋ฃ์ ํธ์ถ
public void disconnect()
{
System.out.println("close : " + url);
}
}
Test Code
package hello.core.lifecycle;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class BeanLifeCycleTest {
@Test
public void lifeCycleTest()
{
ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
NetworkClient client = ac.getBean(NetworkClient.class);
ac.close();
}
@Configuration
static class LifeCycleConfig{
@Bean
public NetworkClient networkClient()
{
NetworkClient networkClient = new NetworkClient();
networkClient.setUrl("http://hello-spring.dev");
return networkClient;
}
}
}
์คํํด๋ณด๋ฉด
์ด์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
์คํ๋ง ๋น์ ๋ค์๊ณผ ๊ฐ์ LifeCycle์ ๊ฐ์ง๋ค.
๊ฐ์ฒด ์์ฑ -> ์์กด๊ด๊ณ ์ฃผ์
์คํ๋ง ๋น์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์์กด๊ด๊ณ ์ฃผ์ ์ด ๋ค ๋๋ ํ์์ผ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ค๋น๊ฐ ์๋ฃ๋๋ค.
๋ฐ๋ผ์ ์ด๊ธฐํ ์์ ์ ์์กด๊ด๊ณ ์ฃผ์ ์ด ๋ชจ๋ ์๋ฃ๋๊ณ ๋ ๋ค์์ ํธ์ถํด์ผ ํ๋ค.
์คํ๋ง์ ์์กด๊ด๊ณ ์ฃผ์ ์ด ์๋ฃ๋๋ฉด ๋น์๊ฒ ์ฝ๋ฐฑ ๋ฉ์๋๋ฅผ ํตํด ์ด๊ธฐํ ์์ ์ ์๋ ค์ฃผ๋ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํจ.
๋ํ ์คํ๋ง ์ปจํ ์ด๋๊ฐ ์ข ๋ฃ๋๊ธฐ ์ง์ ์ ์๋ฉธ ์ฝ๋ฐฑ์ ์ฃผ๋ ๊ธฐ๋ฅ์ด ์์ด ์์ ํ๊ฒ ์ข ๋ฃ ์์ ์ ์งํํ ์ ์์.
์คํ๋ง ๋น์ Lifecycle
์คํ๋ง ์ปจํ ์ด๋ ์์ฑ -> ์คํ๋ง ๋น ์์ฑ -> ์์กด๊ด๊ณ ์ฃผ์ -> ์ด๊ธฐํ ์ฝ๋ฐฑ -> ์ฌ์ฉ -> ์๋ฉธ ์ ์ฝ๋ฐฑ -> ๋น ์๋ฉธ -> ์คํ๋ง ์ข ๋ฃ
์ด๊ธฐํ ์ฝ๋ฐฑ : ๋น์ด ์์ฑ๋๊ณ , ์์กด๊ด๊ณ ์ฃผ์ ์ด ์๋ฃ๋ ํ ํธ์ถ
์๋ฉธ ์ ์ฝ๋ฐฑ : ๋น์ด ์๋ฉธ๋๊ธฐ ์ง์ ์ ํธ์ถ
Tip : ๊ฐ์ฒด์ ์์ฑ๊ณผ ์ด๊ธฐํ๋ฅผ ๋ถ๋ฆฌํ์.
์์ฑ์๋ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์ฑ ์์ ๊ฐ์ง๋ค.
์ด๊ธฐํ๋ ์ด๋ ๊ฒ ์์ฑ๋ ๊ฐ๋ค์ ํ์ฉํด ์ธ๋ถ ์ปค๋ฅ์ ์ ์ฐ๊ฒฐํ๋ ๋ฑ ๋ฌด๊ฑฐ์ด ๋์์ ์ํํ๋ค.
๋ฐ๋ผ์ ์์ฑ์ ์์์ ๋ฌด๊ฑฐ์ด ์ด๊ธฐํ ์์ ์ ๋ณํํด์ ํ๋ ๊ฒ๋ณด๋ค ๋์์ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ ์ง๋ณด์ ๊ด์ ์์ ์ข๋ค.
๋ฌผ๋ก ์ด๊ธฐํ ์์ ์ด ๋ด๋ถ ๊ฐ๋ค๋ง ์ฝ๊ฐ ๋ณ๊ฒฝํ๋ ์ ๋๋ก ๋จ์ํ ๊ฒฝ์ฐ๋ ์์ธ.
์คํ๋ง์ ํฌ๊ฒ 3๊ฐ์ง ๋น Life-cycle callback์ ์ง์ํ๋ค.
1. ์ธํฐํ์ด์ค (InitializingBean, DisposableBean)
2. Config ์ ๋ณด์ ์ด๊ธฐํ ๋ฉ์๋, ์ข ๋ฃ ๋ฉ์๋ ์ง์
3. @PostConstruct, @PreDestroy ์ด๋ ธํ ์ด์
1. ์ธํฐํ์ด์ค (InitializingBean, DisposableBean)
InitializingBean์ afterPropertiesSet()๋ฉ์๋๋ก ์ด๊ธฐํ๋ฅผ ์ง์ํ๋ค.
DisposableBean์ destroy() ๋ฉ์๋๋ก ์๋ฉธ์ ์ง์ํ๋ค.
package hello.core.lifecycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class NetworkClient implements InitializingBean, DisposableBean{
private String url;
public NetworkClient()
{
System.out.println("์์ฑ์ ํธ์ถ, url = " + url);
}
@Override
public void afterPropertiesSet() throws Exception {
connect();
call("์ด๊ธฐํ ์ฐ๊ฒฐ ๋ฉ์์ง");
}
public void setUrl(String url) {
this.url = url;
}
public void connect()
{
System.out.println("connect : " + url);
}
public void call(String message)
{
System.out.println("call: " + url + " message : " + message);
}
@Override
public void destroy() throws Exception {
disconnect();
}
// ์๋น์ค ์ข
๋ฃ์ ํธ์ถ
public void disconnect()
{
System.out.println("close : " + url);
}
}
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ์ด๊ธฐํ ๋ฉ์๋๊ฐ ์ฃผ์ ์๋ฃ ํ ์ ์ ํ๊ฒ ํธ์ถ ๋ ๊ฒ์ ํ์ธ ๊ฐ๋ฅ.
๊ทธ๋ฆฌ๊ณ ์คํ๋ง ์ปจํ ์ด๋์ ์ข ๋ฃ๊ฐ ํธ์ถ๋์ ์๋ฉธ ๋ฉ์๋๊ฐ ํธ์ถ ๋ ๊ฒ์ ํ์ธ ๊ฐ๋ฅ.
์ด๊ธฐํ, ์๋ฉธ ์ธํฐํ์ด์ค ๋จ์ .
์คํ๋ง ์ ์ฉ ์ธํฐํ์ด์ค๋ผ๋ ์ธก๋ฉด์์ ์์กด์ ์ด๋ค.
์ด๊ธฐํ, ์๋ฉธ ๋ฉ์๋์ ์ด๋ฆ์ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ๋ค. (์ธํฐํ์ด์ค)
๋ด๊ฐ ์ฝ๋๋ฅผ ๊ณ ์น ์ ์๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ์ฉํ ์ ์๋ค.
์ธํฐํ์ด์ค๋ ์ด์ฐฝ๊ธฐ์ ๋์จ ๋ฐฉ๋ฒ๋ค์ด๊ณ , ์ง๊ธ์ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋๋ค.
2. Config ์ ๋ณด์ ์ด๊ธฐํ ๋ฉ์๋, ์ข ๋ฃ ๋ฉ์๋ ์ง์
์ค์ ์ ๋ณด์ @Bean(initMethod = "init", destroyMethod = "close)์ฒ๋ผ ์ด๊ธฐํ ์๋ฉธ ๋ฉ์๋๋ฅผ ์ง์ ํ ์ ์์.
public void init()
{
System.out.println("NetworkClient.init");
connect();
call("์ด๊ธฐํ ์ฐ๊ฒฐ ๋ฉ์์ง");
}
public void close()
{
System.out.println("NetworkClient.close");
disconnect();
}
package hello.core.lifecycle;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class BeanLifeCycleTest {
@Test
public void lifeCycleTest()
{
ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
NetworkClient client = ac.getBean(NetworkClient.class);
ac.close();
}
@Configuration
static class LifeCycleConfig{
@Bean(initMethod = "init" , destroyMethod = "close")
public NetworkClient networkClient()
{
NetworkClient networkClient = new NetworkClient();
networkClient.setUrl("http://hello-spring.dev");
return networkClient;
}
}
}
ํน์ง
๋ฉ์๋ ์ด๋ฆ์ ์์ ๋กญ๊ฒ ์ค ์ ์๋ค.
์คํ๋ง ๋น์ด ์คํ๋ง ์ฝ๋์ ์์กดํ์ง ์์.
์ฝ๋๊ฐ ์๋ ์ค์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ฝ๋๋ฅผ ๊ณ ์น ์ ์๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์๋ ์ด๊ธฐํ, ์ข ๋ฃ ๋ฉ์๋ ์ ์ฉ ๊ฐ๋ฅ
@Bean destroyMethod ์์ฑ์ ์ถ๋ก (inferred) ๊ธฐ๋ฅ
- ์ง์ ํ์ง ์๋ ๊ฒฝ์ฐ close , shutdown๋ผ๋ ์ด๋ฆ์ ๋ฉ์๋๋ฅผ ์๋์ผ๋ก ํธ์ถํด์ค๋ค.
- ์ถ๋ก ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ซ์ผ๋ฉด ๋น ๊ณต๋ฐฑ์ ์ง์ ํ๋ฉด ๋๋ค. ""
3. @PostConstruct, @PreDestroy
@PostConstruct
public void init()
{
System.out.println("NetworkClient.init");
connect();
call("์ด๊ธฐํ ์ฐ๊ฒฐ ๋ฉ์์ง");
}
@PreDestroy
public void close()
{
System.out.println("NetworkClient.close");
disconnect();
}
@PostConstruct , @PreDestroy ์ด ๋ ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ๊ฐ์ฅ ํธ๋ฆฌํ๊ฒ ์ด๊ธฐํ์ ์ข ๋ฃ๋ฅผ ์คํํ ์ ์๋ค.
ํน์ง
1. ์ต์ ์คํ๋ง์์ ๊ฐ์ฅ ๊ถ์ฅํ๋ ๋ฐฉ๋ฒ
2. ์ด๋ ธํ ์ด์ ํ๋๋ง ๋ถ์ด๋ฉด ๋๋ฏ๋ก ๋งค์ฐ ํธ๋ฆฌ.
3. javax ํจํค์ง๋ก ์คํ๋ง ์ข ์ ๊ธฐ์ ์ด ์๋๋ผ ์๋ฐ ํ์ค ๊ธฐ์ ์ด๋ผ ์คํ๋ง์ด ์๋ ๋ค๋ฅธ ์ปจํ ์ด๋์์๋ ์๋
4. ์ปดํฌ๋ํธ ์ค์บ๊ณผ ์ ์ด์ธ๋ฆผ
5. ๋จ์ ์ผ๋ก๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์๋ ์ ์ฉํ์ง ๋ชปํจ.
<์ ๋ฆฌ>
@PostConstruct, @PreDestroy ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋, ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด๊ธฐํ, ์ข ๋ฃํด์ผํ๋ฉด @Bean์ initMethod, destroyMethod๋ฅผ ์ฌ์ฉํ์.
<์ฐธ๊ณ ์๋ฃ>
'๐ Backend' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring / Web ์ค์ฝํ (0) | 2023.02.13 |
---|---|
Spring / Bean Scope (0) | 2023.02.11 |
Spring / List,Map์ ์ด์ฉํ ๋์ผํ์ ๋น ์ฌ์ฉ, ์๋๊ณผ ์๋์ ์ฌ๋ฐ๋ฅธ ์ค๋ฌด ์ด์ ๊ธฐ์ค (0) | 2023.02.08 |
Spring / @Qualifier, @Primary (0) | 2023.02.07 |
Spring / ๋กฌ๋ณต ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ ์ฝ๋ ์ต์ ํ (0) | 2023.02.06 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422