Customize Bean

Spring Framework๋Š” Bean์˜ ํŠน์„ฑ์„ ๋งž์ถค ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ์„น์…˜์—์„œ๋Š” ์ด๋ฅผ ๋ช‡ ๊ฐ€์ง€๋กœ ๊ทธ๋ฃนํ™”ํ•˜์—ฌ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค:

  1. Lifecycle Callbacks (์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ)

  2. ApplicationContextAware ๋ฐ BeanNameAware

  3. ๊ธฐํƒ€ Aware ์ธํ„ฐํŽ˜์ด์Šค

Lifecycle Callbacks

Spring ์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” Bean์˜ ์ƒ๋ช…์ฃผ๊ธฐ(lifecycle)์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋ ค๋ฉด, InitializingBean๊ณผ DisposableBean ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • InitializingBean ์ธํ„ฐํŽ˜์ด์Šค๋Š” afterPropertiesSet() ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์—ฌ Bean์ด ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

  • DisposableBean ์ธํ„ฐํŽ˜์ด์Šค๋Š” destroy() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด Bean์ด ํŒŒ๊ดด๋  ๋•Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@PostConstruct์™€ @PreDestroy ์• ๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ชจ๋˜ํ•œ Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ƒ๋ช…์ฃผ๊ธฐ ์ฝœ๋ฐฑ์„ ๋ฐ›๋Š” ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Bean์ด Spring์— ์ข…์†๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋” ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

InitializingBean

Spring์—์„œ ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด InitializingBean ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , afterPropertiesSet() ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” Spring ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ•ด๋‹น Bean์— ํ•„์š”ํ•œ ๋ชจ๋“  ์†์„ฑ์„ ์„ค์ •ํ•œ ํ›„์— ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean {
    public void init() {
        // Bean ์ดˆ๊ธฐํ™” ์ž‘์—… ์ˆ˜ํ–‰
    }
}

์œ„์˜ ์˜ˆ์‹œ๋Š” InitializingBean์„ ์ง์ ‘ ๊ตฌํ˜„ํ•œ ์˜ˆ์‹œ์™€ ๊ฑฐ์˜ ๋™์ผํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

public class AnotherExampleBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() {
        // Bean ์ดˆ๊ธฐํ™” ์ž‘์—… ์ˆ˜ํ–‰
    }
}

์ฃผ์˜: @PostConstruct์™€ ์ดˆ๊ธฐํ™” ๋ฉ”์„œ๋“œ๋Š” Bean์ด ์™„์ „ํžˆ ์ดˆ๊ธฐํ™”๋œ ํ›„์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ๋Š” ์™ธ๋ถ€ Bean๊ณผ์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ํ•˜๊ธฐ ์ „์— ๋‚ด๋ถ€์ ์ธ ์ดˆ๊ธฐํ™”๋งŒ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด **์ดˆ๊ธฐํ™” ๊ต์ฐฉ ์ƒํƒœ(deadlock)**๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ํ›„์† ์ดˆ๊ธฐํ™” ์ž‘์—…

๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ดˆ๊ธฐํ™” ์ž‘์—…(์˜ˆ: ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ค€๋น„)์„ ํŠธ๋ฆฌ๊ฑฐํ•ด์•ผ ํ•  ๊ฒฝ์šฐ์—๋Š” SmartInitializingSingleton.afterSingletonsInstantiated() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ContextRefreshedEvent๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ApplicationListener๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๋ชจ๋“  ์‹ฑ๊ธ€ํ†ค ์ดˆ๊ธฐํ™”๊ฐ€ ๋๋‚œ ํ›„์— ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.


DisposableBean

Bean์ด ํŒŒ๊ดด๋  ๋•Œ(์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ข…๋ฃŒ ์‹œ ๋“ฑ) ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด, DisposableBean ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , destroy() ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ์ž‘์—…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<bean id="exampleDestructionBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean {
    public void cleanup() {
        // Bean ํŒŒ๊ดด ์ž‘์—… ์ˆ˜ํ–‰ (์˜ˆ: ๋ฆฌ์†Œ์Šค ํ•ด์ œ)
    }
}

์ด ์˜ˆ์‹œ๋Š” DisposableBean ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๋‹ค์Œ์˜ ์˜ˆ์‹œ์™€ ๋™์ผํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค:

public class AnotherExampleBean implements DisposableBean {
    @Override
    public void destroy() {
        // Bean ํŒŒ๊ดด ์ž‘์—… ์ˆ˜ํ–‰
    }
}

์ฃผ์˜: Bean์„ ํŒŒ๊ดดํ•  ๋•Œ๋„ @PreDestroy ์• ๋…ธํ…Œ์ด์…˜์ด๋‚˜ destroy-method ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋˜๋ฉฐ, Spring์— ์ข…์†๋˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


Default Initialization and Destroy Methods

๊ธฐ๋ณธ ์ดˆ๊ธฐํ™”/ํŒŒ๊ดด ๋ฉ”์„œ๋“œ ์„ค์ •: Spring์—์„œ๋Š” Bean์— ๋Œ€ํ•ด ์ผ๊ด€๋œ ๋ผ์ดํ”„์‚ฌ์ดํด ์ฝœ๋ฐฑ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋ชจ๋“  Bean์—์„œ ์ดˆ๊ธฐํ™” ๋ฉ”์„œ๋“œ๊ฐ€ init()์ด๊ณ , ํŒŒ๊ดด ๋ฉ”์„œ๋“œ๊ฐ€ destroy()๋ผ๋ฉด, ๊ฐ Bean ์ •์˜๋งˆ๋‹ค ๋ฉ”์„œ๋“œ๋ฅผ ๋ช…์‹œํ•  ํ•„์š” ์—†์ด default-init-method์™€ default-destroy-method ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ „์—ญ์œผ๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<beans default-init-method="init" default-destroy-method="destroy">
    <bean id="myService" class="com.example.MyService"/>
</beans>

์ด ๊ฒฝ์šฐ, MyService ํด๋ž˜์Šค์— init()๊ณผ destroy() ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, Bean์ด ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜ ํŒŒ๊ดด๋  ๋•Œ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.


ApplicationContextAware ๋ฐ BeanNameAware

ApplicationContextAware: Bean์ด ApplicationContext๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ์„ค์ •ํ•˜๋ ค๋ฉด ApplicationContextAware ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ setApplicationContext() ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ฉ๋‹ˆ๋‹ค.

public class MyBean implements ApplicationContextAware {
    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}
  • BeanNameAware: Bean์ด ์ž์‹ ์˜ ์ด๋ฆ„์„ ์ฐธ์กฐํ•˜๋„๋ก ์„ค์ •ํ•˜๋ ค๋ฉด BeanNameAware ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ setBeanName() ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ฉ๋‹ˆ๋‹ค.

    public class MyBean implements BeanNameAware {
        @Override
        public void setBeanName(String name) {
            System.out.println("Bean name: " + name);
        }
    }

์ด ์ธํ„ฐํŽ˜์ด์Šค๋“ค์€ Bean์ด ์ž์‹ ์„ ์ƒ์„ฑํ•œ ์ปจํ…Œ์ด๋„ˆ๋‚˜ ์ž์‹ ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.


3. ๊ธฐํƒ€ Aware ์ธํ„ฐํŽ˜์ด์Šค

Spring์€ ์ถ”๊ฐ€์ ์œผ๋กœ ๋‹ค์–‘ํ•œ Aware ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜์—ฌ Bean์ด ํ•„์š”ํ•œ ์ธํ”„๋ผ ์ข…์†์„ฑ์„ ์ปจํ…Œ์ด๋„ˆ๋กœ๋ถ€ํ„ฐ ์ œ๊ณต๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์ธ Aware ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

์ธํ„ฐํŽ˜์ด์Šค

์ฃผ์ž…๋˜๋Š” ์˜์กด์„ฑ

์„ค๋ช…

ApplicationContextAware

ApplicationContext

์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

BeanClassLoaderAware

Bean ํด๋ž˜์Šค ๋กœ๋”

Bean ํด๋ž˜์Šค ๋กœ๋”๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

BeanFactoryAware

BeanFactory

BeanFactory๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

ResourceLoaderAware

ResourceLoader

๋ฆฌ์†Œ์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋กœ๋”์ž…๋‹ˆ๋‹ค.

MessageSourceAware

MessageSource

๋ฉ”์‹œ์ง€ ํ•ด๊ฒฐ ์ „๋žต์„ ์ฃผ์ž…๋ฐ›์Šต๋‹ˆ๋‹ค.

ServletContextAware

ServletContext (์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ)

ํ˜„์žฌ ServletContext๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

์ด ์ธํ„ฐํŽ˜์ด์Šค๋“ค์€ ์ฃผ๋กœ ์ธํ”„๋ผ์— ๊ฐ€๊นŒ์šด Bean์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ์ผ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ๋Š” Spring์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด ํ”ผํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.


Lifecycle ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•œ Startup ๋ฐ Shutdown ์ฝœ๋ฐฑ

Spring์—์„œ๋Š” Lifecycle ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ Bean์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ์‹œ์ž‘๋˜๊ฑฐ๋‚˜ ์ข…๋ฃŒ๋  ๋•Œ ์ž๋™์œผ๋กœ ์‹œ์ž‘/์ข…๋ฃŒ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

public interface Lifecycle {
    void start();
    void stop();
    boolean isRunning();
}

์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋˜๊ฑฐ๋‚˜ ์ค‘์ง€๋  ๋•Œ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฐ์ฒด์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰๋˜๋Š” ์„œ๋น„์Šค๊ฐ€ ์žˆ์„ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • SmartLifecycle ์ธํ„ฐํŽ˜์ด์Šค๋Š” Lifecycle์„ ํ™•์žฅํ•˜๋ฉฐ, ๋” ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, getPhase() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด Bean์ด ์‹œ์ž‘๋˜๊ฑฐ๋‚˜ ์ข…๋ฃŒ๋  ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

public interface SmartLifecycle extends Lifecycle, Phased {
    boolean isAutoStartup();
    void stop(Runnable callback);
}

getPhase() ๋ฉ”์„œ๋“œ๋Š” ์‹œ์ž‘ ์ˆœ์„œ์™€ ์ข…๋ฃŒ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋ฉฐ, ๊ฐ’์ด ๋‚ฎ์„์ˆ˜๋ก ๋จผ์ € ์‹œ์ž‘๋˜๊ณ  ๋‚˜์ค‘์— ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

Last updated

Was this helpful?