๐Ÿ”ฅ TIL - Day 81 BeanPostProcessor ๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ

Kim Dae Hyunยท2022๋…„ 1์›” 13์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
92/93

์„ค์ •ํŒŒ์ผ์„ ์ด์šฉํ•ด์„œ ์ง์ ‘ Bean์„ ๋“ฑ๋กํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹Œ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ์ด์šฉํ•ด์„œ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— Bean์„ ๋“ฑ๋กํ•˜๋Š” ๊ฒฝ์šฐ ๋“ฑ๋ก๋˜๋Š” Bean์— ๋Œ€ํ•ด ์กฐ์ž‘ํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค. (์ปดํฌ๋„ŒํŠธ ์Šค์บ”์— ์˜ํ•ด ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ)

์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ํ†ตํ•ด ๋“ฑ๋ก๋˜๋Š” Bean์„ ๋Œ€์‹ ํ•ด์„œ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ด๋‹ค.

๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋˜๋Š” ๋ชจ๋“  ๋นˆ์— ๋Œ€ํ•ด ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๋„์™€์ค€๋‹ค.
๋“ฑ๋ก๋˜๋Š” Bean์— ๋Œ€ํ•ด์„œ ์ถ”๊ฐ€์ ์ธ ์ž‘์—…๋„ ๊ฐ€๋Šฅํ•˜๊ณ  ๋™์ผํ•œ Bean์ด๋ฆ„์œผ๋กœ ์•„์˜ˆ ๋‹ค๋ฅธ Bean์„ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.


๐Ÿ“Œ ๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ ์˜ˆ์ œ

์˜ˆ์ œ ์‹œ๋‚˜๋ฆฌ์˜ค

  • ๋‘ ๊ฐœ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  (Aํด๋ž˜์Šค, Bํด๋ž˜์Šค) Aํด๋ž˜์Šค๋งŒ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— Bean์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค.
  • ๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ์—์„œ Aํƒ€์ž…์œผ๋กœ ๋“ฑ๋ก๋˜๋Š” Bean์„ Bํƒ€์ž…์œผ๋กœ ๋ฐ”๊ฟ”์„œ ๋“ฑ๋กํ•œ๋‹ค.
  • ๊ฒฐ๊ณผ์ ์œผ๋กœ Bean์ด A์ด๋ฆ„์œผ๋กœ Bํƒ€์ž… ๊ฐ์ฒด๊ฐ€ Bean์„ ๋“ฑ๋ก๋˜๋Š” ๊ฒƒ๊ณผ Aํƒ€์ž…์œผ๋กœ ๋“ฑ๋ก๋œ Bean์ด ์—†๋Š” ๊ฒƒ์„ ํ™•์ธํ•œ๋‹ค.

๋‘ ๊ฐœ ํด๋ž˜์Šค ์ƒ์„ฑ

    @Slf4j
    static class A {
        public void call() {
            log.info("Test A");
        }
    }

    @Slf4j
    static class B {
        public void call() {
            log.info("Test B");
        }
    }

Aํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋งŒ Bean์œผ๋กœ ๋“ฑ๋ก

    @Configuration
    static class BeanPostProcessorTestConfig {
        @Bean // A๋งŒ ๋นˆ์œผ๋กœ ๋“ฑ๋ก
        public A a() {
            return new A();
        }
    }

๋นˆํ›„์ฒ˜๋ฆฌ๊ธฐ ๊ตฌํ˜„
๋นˆํ›„์ฒ˜๋ฆฌ๊ธฐ๋Š” BeanPostProcessor ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๊ตฌํ˜„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

@Slf4j
static class AToBPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("bean={}, beanName={}", bean, beanName);

        // ๋“ฑ๋ก๋˜๋Š” ๋นˆ์ด A ํƒ€์ž…์ด๋ผ๋ฉด B์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋“ฑ๋กํ•˜๋„๋ก ์ฒ˜๋ฆฌ (Hooking)
        // ๋“ฑ๋ก๋˜๋Š” ๋นˆ์˜ ์ด๋ฆ„์€ ๊ทธ๋Œ€๋กœ 'a' ์ด์ง€๋งŒ ๋นˆ์˜ ์‹ค์ œ ๊ฐ์ฒด๋Š” B ํƒ€์ž…์ด ๋œ๋‹ค.
        if (bean instanceof A) return new B();
        return bean;
    }
}

๊ตฌํ˜„๋œ ๋นˆํ›„์ฒ˜๋ฆฌ๊ธฐ๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค.

    @Configuration
    static class BeanPostProcessorTestConfig {
        @Bean // A๋งŒ ๋นˆ์œผ๋กœ ๋“ฑ๋ก
        public A a() {
            return new A();
        }

        @Bean // ๋นˆํ›„์ฒ˜๋ฆฌ๊ธฐ ๋“ฑ๋ก
        public AToBPostProcessor postProcessor() {
            return new AToBPostProcessor();
        }
    }

ํ…Œ์ŠคํŠธ

  • a๋กœ ๋“ฑ๋ก๋œ Bean์„ Bํด๋ž˜์Šค ํƒ€์ž…์œผ๋กœ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.
  • Aํด๋ž˜์Šค ํƒ€์ž…์œผ๋กœ ๋“ฑ๋ก๋œ Bean ์ž์ฒด๊ฐ€ ์—†์–ด์•ผ ํ•œ๋‹ค. (Aํƒ€์ž… Bean์ด ๋“ฑ๋ก๋  ๋•Œ Bํƒ€์ž… Bean์„ ๋“ฑ๋กํ–ˆ๊ธฐ ๋•Œ๋ฌธ)
@Test
void basicConfig() {
    ApplicationContext context = new AnnotationConfigApplicationContext(BeanPostProcessorTestConfig.class);
    B b = context.getBean("a", B.class);
    b.call();

    Assertions.assertThrows(NoSuchBeanDefinitionException.class, () -> context.getBean(A.class));
}


๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์ด์šฉํ•ด์„œ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์— ์˜ํ•ด ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋˜๋Š” Bean์— ๋Œ€ํ•ด์„œ๋„ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์œผ๋กœ ๋“ฑ๋ก๋˜๋Š” Bean์— ๋Œ€ํ•ด์„œ๋„ ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ๋Œ€์‹ ํ•ด์„œ ๋“ฑ๋ก๋˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.


๐Ÿ“Œ ์ฐธ๊ณ 

์ธํ”„๋Ÿฐ - ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ ๊ณ ๊ธ‰ํŽธ (๊น€์˜ํ•œ ๋‹˜)

profile
์ข€ ๋” ์ฒœ์ฒœํžˆ ๊นŒ๋จน๊ธฐ ์œ„ํ•ด ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ๐Ÿง

0๊ฐœ์˜ ๋Œ“๊ธ€