[Spring] 빈 ν›„μ²˜λ¦¬κΈ°, Bean Postprocessor

2022. 6. 4. 10:51γ†πŸŒΏ Spring

μž μ‹œ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ λΉˆμ„ κ΄€λ¦¬ν•˜λŠ” 방식을 μ§šμ–΄λ³΄μž.

@Bean μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜κ±°λ‚˜, μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ”μœΌλ‘œ μŠ€ν”„λ§ λΉˆμ„ λ“±λ‘ν•˜λ©΄ μŠ€ν”„λ§μ€ λŒ€μƒ 객체λ₯Ό μƒμ„±ν•˜κ³  μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ λ‚΄λΆ€μ˜ 빈 μ €μž₯μ†Œμ— λ“±λ‘ν•œλ‹€. 이제 μ»¨ν…Œμ΄λ„ˆμ— λ“±λ‘λœ μŠ€ν”„λ§ λΉˆμ„ μ‘°νšŒν•˜μ—¬ ν•„μš”ν•  λ•Œ ν•΄λ‹Ή λΉˆμ„ μ‚¬μš©ν•œλ‹€. 

 

이전 ν¬μŠ€νŠΈμ—μ„œ ν”„λ‘μ‹œλ₯Ό μ„€μ •ν•œ 방법을 μƒκ°ν•΄λ³΄μž. 

μ‹€μ œ 객체λ₯Ό μŠ€ν”„λ§ 빈으둜 λ“±λ‘ν•˜λŠ” 것이 μ•„λ‹Œ ProxyFactoryConfigV1 처럼, λΆ€κ°€ κΈ°λŠ₯이 μžˆλŠ” ν”„λ‘μ‹œλ₯Ό μ‹€μ œ 객체 λŒ€μ‹  μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— 빈으둜 등둝해야 ν•œλ‹€. 그럼 Component Scan λ°©μ‹μœΌλ‘œ λΉˆμ„ λ“±λ‘ν•˜λŠ” κ²½μš°μ—” μ–΄λ–»κ²Œ ν”„λ‘μ‹œ 섀정을 ν•  수 μžˆμ„κΉŒ? 이미 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— 등둝이 됐기 λ•Œλ¬Έμ— ν”„λ‘μ‹œλ₯Ό μ‹€μ œ 객체 λŒ€μ‹  등둝할 수 도 μ—†κ²Œ 됐닀. 

λ§Œμ•½ μ‹€μ œ 객체가 μŠ€ν”„λ§ 빈으둜 λ“±λ‘λ˜κΈ° 직전에 ν”„λ‘μ‹œ 객체둜 λŒ€μ²΄ν•  수 μžˆλ‹€λ©΄, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„Œμ— ν”„λ‘μ‹œ 객체λ₯Ό λŒ€μ‹  등둝할 수 μžˆμ„ 것이닀. 이λ₯Ό μœ„ν•΄ μš°λ¦¬λŠ” 빈 ν›„μ²˜λ¦¬κΈ° λΌλŠ” κΈ°μˆ μ„ μ•Œμ•„λ³΄κ² λ‹€. 

 

ProxyFactoryConfigV1

@Slf4j
@Configuration
public class ProxyFactoryConfigV1 {

    @Bean // 빈 λ§ˆλ‹€ ν”„λ‘μ‹œ νŒ©ν† λ¦¬λ₯Ό μƒμ„±ν•΄μ•Όν•œλ‹€.
    public OrderControllerV1 orderControllerV1(LogTrace logTrace) {
        OrderControllerV1 orderController = new OrderControllerV1Impl(orderServiceV1(logTrace));
        ProxyFactory factory = new ProxyFactory(orderController);
        factory.addAdvisor(getAdvisor(logTrace));
        OrderControllerV1 proxy = (OrderControllerV1) factory.getProxy();
        log.info("ProxyFactory proxy={}, target={}", proxy.getClass(), orderController.getClass());
        return proxy;
    }

    @Bean
    public OrderServiceV1 orderServiceV1(LogTrace logTrace) {
        OrderServiceV1 orderService = new OrderServiceV1Impl(orderRepositoryV1(logTrace));
        ProxyFactory factory = new ProxyFactory(orderService);
        factory.addAdvisor(getAdvisor(logTrace));
        OrderServiceV1 proxy = (OrderServiceV1) factory.getProxy();
        log.info("ProxyFactory proxy={}, target={}", proxy.getClass(), orderService.getClass());
        return proxy;
    }

    @Bean
    public OrderRepositoryV1 orderRepositoryV1(LogTrace logTrace) {
        OrderRepositoryV1Impl orderRepository = new OrderRepositoryV1Impl();

        ProxyFactory factory = new ProxyFactory(orderRepository);
        factory.addAdvisor(getAdvisor(logTrace));
        OrderRepositoryV1 proxy = (OrderRepositoryV1) factory.getProxy();
        log.info("ProxyFactory proxy={}, target={}", proxy.getClass(), orderRepository.getClass());
        return proxy;
    }

    private Advisor getAdvisor(LogTrace logTrace) {
        NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
        pointcut.setMappedNames("request*", "order*", "save*");  // no-log μ œμ™Έν•˜κΈ° μœ„ν•¨..?
        LogTraceAdvice advice = new LogTraceAdvice(logTrace);
        return new DefaultPointcutAdvisor(pointcut, advice);
    }
}

 

 

빈 ν›„μ²˜λ¦¬κΈ° - BeanPostProcessor

빈 ν›„μ²˜λ¦¬κΈ°λŠ” μŠ€ν”„λ§ 빈 μ €μž₯μ†Œμ— 등둝할 λͺ©μ μœΌλ‘œ μƒμ„±ν•œ 객체λ₯Ό 빈 μ €μž₯μ†Œμ— λ“±λ‘ν•˜κΈ° 직전에 μ‘°μž‘ν•˜κ³  싢을 λ•Œ μ‚¬μš©ν•  수 μžˆλ‹€. 빈 ν›„μ²˜λ¦¬κΈ°λŠ” 객체λ₯Ό μ‘°μž‘ν•  수 있고, μ™„μ „νžˆ λ‹€λ₯Έ 객체둜 λ°”κΏ”μΉ˜κΈ° ν•˜λŠ” 것도 κ°€λŠ₯ν•˜λ‹€. 

 

빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό ν†΅ν•œ 빈 등둝 κ³Όμ •

  1. 생성 : μŠ€ν”„λ§ 빈 λŒ€μƒμ΄ λ˜λŠ” 객체λ₯Ό μƒμ„±ν•œλ‹€. (@Bean μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ” 포함)
  2. 전달 : μƒμ„±λœ 객체λ₯Ό 빈 μ €μž₯μ†Œμ— λ“±λ‘ν•˜κΈ° 직전에 빈 ν›„μ²˜λ¦¬κΈ°μ— λ“±λ‘ν•œλ‹€. 
  3. ν›„ 처리 μž‘μ—… : 빈 ν›„μ²˜λ¦¬κΈ°λŠ” 전달받은 빈 객체λ₯Ό μ‘°μž‘ν•˜κ±°λ‚˜ λ‹€λ₯Έ 객체( 예λ₯Ό λ“€μ–΄ ν”„λ‘μ‹œ 객체 λ“± ) 둜 λ°”κΏ”μΉ˜κΈ° ν•  수 μžˆλ‹€.
  4. 등둝 : 빈 ν›„μ²˜λ¦¬κΈ°λŠ” λΉˆμ„ λ°˜ν™˜ν•œλ‹€. 전달 된 λΉˆμ„ κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜λ©΄ ν•΄λ‹Ή 빈이, λ°”κΏ”μΉ˜κΈ° ν•˜λ©΄ λ‹€λ₯Έ 객체가 빈 μ €μž₯μ†Œμ— λ“±λ‘λœλ‹€. 

빈 ν›„μ²˜λ¦¬κΈ° 적용 - μ˜ˆμ‹œ μ½”λ“œ

public class BeanPostProcessorTest {

    @Test
    void basicConfig() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(
            BeanPostProcessorConfig.class);

        // beanA μ΄λ¦„μœΌλ‘œ B 객체가 빈으둜 λ“±λ‘λœλ‹€.
        B b = applicationContext.getBean("beanA", B.class);
        b.helloB();

        // AλŠ” 빈으둜 λ“±λ‘λ˜μ§€ μ•ŠλŠ”λ‹€.
        Assertions.assertThrows(NoSuchBeanDefinitionException.class,
            () -> applicationContext.getBean(A.class));
    }

    @Slf4j
    @Configuration
    static class BeanPostProcessorConfig {

        @Bean(name = "beanA")
        public A a() {
            return new A();
        }

        @Bean // BeanPostProcessor λ₯Ό κ΅¬ν˜„ν•œ 클래슀λ₯Ό 빈으둜 λ“±λ‘ν•˜λ©΄ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ μžλ™μœΌλ‘œ 빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό μΈμ‹ν•˜κ³  λ™μž‘μ‹œν‚¨λ‹€.
        public AToBPostProcessor helloPostProcessor() {
            return new AToBPostProcessor();
        }
    }

    @Slf4j
    static class A {

        public void helloA() {
            log.info("hello A");
        }
    }

    @Slf4j
    static class B {

        public void helloB() {
            log.info("hello B");
        }
    }

    @Slf4j
    static class AToBPostProcessor implements BeanPostProcessor {

        public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
            log.info("beanName={} bean={}", beanName, bean);
            if (bean instanceof A) {
                return new B();
            }
            return bean;
        }
    }
}

 

AToBPostProcessor

  • 빈 ν›„μ²˜λ¦¬κΈ° 클래슀둜, μΈν„°νŽ˜μ΄μŠ€μΈ BeanPostProcessor λ₯Ό κ΅¬ν˜„ν•˜λ©΄, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ μžλ™μœΌλ‘œ 빈 ν›„μ²˜λ¦¬κΈ°λ‘œ μΈμ‹ν•˜κ³  λ™μž‘ν•œλ‹€. 
  • ν•΄λ‹Ή 빈 ν›„μ²˜λ¦¬κΈ°λŠ” A 객체λ₯Ό B 객체둜 λ°”κΏ”μΉ˜κΈ° ν•œλ‹€. 
  • μœ„ μ½”λ“œλ₯Ό μˆœμ„œλŒ€λ‘œ λΆ„μ„ν•΄λ³΄μž. 

μ‹€ν–‰ κ²°κ³Όλ₯Ό 확인해보면 μ΅œμ’…μ μœΌλ‘œ "beanA" λΌλŠ” μŠ€ν”„λ§ 빈 이름에 A 객체 λŒ€μ‹  B 객체가 λ“±λ‘λœ 것을 확인할 수 μžˆλ‹€. Aκ°μ²΄λŠ” 빈으둜 등둝쑰차 λ˜μ§€ μ•Šμ•˜λ‹€. 

 

쀑간 정리

빈 ν›„μ²˜λ¦¬κΈ°λŠ” λΉˆμ„ μ‘°μž‘ν•˜κ³  λ³€κ²½ν•  수 μžˆλŠ” ν›„ν‚Ή ν¬μΈνŠΈλ‹€. 

일반적으둜 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ λ“±λ‘ν•˜λŠ”, (특히 μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ”μ˜ λŒ€μƒμ΄ λ˜λŠ”) μŠ€ν”„λ§ λΉˆμ€ 쀑간에 μ‘°μž‘ν•  방법이 μ—†λŠ”λ°, 빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό μ‚¬μš©ν•˜λ©΄ κ°œλ°œμžκ°€ λ“±λ‘ν•˜λŠ” λͺ¨λ“  λΉˆμ„ 쀑간에 μ‘°μž‘ν•  수 μžˆλ‹€. 즉 μš°λ¦¬κ°€ μ›ν–ˆλ˜, μ‹€μ œ 빈 객체(μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ”μ˜ λŒ€μƒ)λ₯Ό ν”„λ‘μ‹œλ‘œ κ΅μ²΄ν•˜λŠ” 것도 κ°€λŠ₯ν•˜λ‹€λŠ” μ˜λ―Έλ‹€.

 

 

μŠ€ν”„λ§μ΄ μ œκ³΅ν•˜λŠ” 빈 ν›„μ²˜λ¦¬κΈ°

μœ„μ˜ 방법을 μ΄μš©ν•˜λ©΄ (BeanPostProcessor λ₯Ό κ΅¬ν˜„ν•΄ μŠ€ν”„λ§ Config 둜 직접 등둝) ν”„λ‘μ‹œ 생성에 빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό μ μš©ν•  수 μžˆμ§€λ§Œ, μŠ€ν”„λ§μ€ 이미 ν”„λ‘μ‹œλ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ 빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό λ§Œλ“€μ–΄ μ œκ³΅ν•œλ‹€. 

 

 

μžλ™ ν”„λ‘μ‹œ 생성기 - AutoProxyCreator

이 라이브러리λ₯Ό μΆ”κ°€ν•˜λ©΄ aspectJ κ΄€λ ¨ 라이브러리λ₯Ό λ“±λ‘ν•˜κ³ , μŠ€ν”„λ§λΆ€νŠΈκ°€ AOP κ΄€λ ¨ 클래슀λ₯Ό μžλ™μœΌλ‘œ μŠ€ν”„λ§ λΉˆμ— λ“±λ‘ν•œλ‹€. 

  implementation 'org.springframework.boot:spring-boot-starter-aop'

이 라이브러리λ₯Ό μΆ”κ°€ν•˜λ©΄, AnnotationAwareAspectJAutoProxyCreator λΌλŠ” 빈 ν›„μ²˜λ¦¬κΈ°κ°€ μŠ€ν”„λ§ 빈으둜 μžλ™ λ“±λ‘λœλ‹€. 이름 κ·ΈλŒ€λ‘œ μžλ™μœΌλ‘œ ν”„λ‘μ‹œλ₯Ό μƒμ„±ν•˜λŠ” 빈 ν›„μ²˜λ¦¬κΈ°λ‹€. (ν•΄λ‹Ή 빈 ν›„μ²˜λ¦¬κΈ°λŠ” μ—¬λŸ¬ λΆ€λͺ¨ 관계λ₯Ό 거쳐 BeanPostProcessor λ₯Ό μƒμ†λ°›λŠ”λ‹€.)

이 빈 ν›„μ²˜λ¦¬κΈ°λŠ” μŠ€ν”„λ§ 빈으둜 λ“±λ‘λœ Advisorλ₯Ό μ°Ύμ•„ ν”„λ‘μ‹œκ°€ ν•„μš”ν•œ 곳에 μžλ™μœΌλ‘œ μ μš©ν•΄μ£ΌλŠ”λ°, Advisor μ—λŠ” 이미 Pointcut κ³Ό Advice κ°€ ν¬ν•¨λ˜μ–΄ 있기 λ•Œλ¬Έμ— κ°€λŠ₯ν•˜λ‹€.  이λ₯Ό μ’€ 더 ν’€μ–΄μ„œ μƒκ°ν•΄λ³΄μž. 

 

μžλ™μœΌλ‘œ ν”„λ‘μ‹œλ₯Ό μƒμ„±ν•˜λŠ” 빈 ν›„μ²˜λ¦¬κΈ°?

μ–΄λ–»κ²Œ ν•˜λ©΄ ν”„λ‘μ‹œλ₯Ό μžλ™μœΌλ‘œ 생성할 수 μžˆμ„κΉŒ? ν”„λ‘μ‹œ 생성에 ν•„μš”ν•œ μš”μ†Œλ₯Ό μ°¨λ‘€λŒ€λ‘œ μƒκ°ν•΄λ³΄μž. μš°μ„  ν”„λ‘μ‹œλ₯Ό μ μš©ν•  λŒ€μƒ 객체(target)κ°€ ν•„μš”ν•˜λ‹€. κ·Έ λ‹€μŒμ—” ν”„λ‘μ‹œ 생성에 ν•„μš”ν•œ ProxyFactory 객체가 ν•„μš”ν•˜κ³ , ProxyFactory 객체에 μ μš©ν•  Advisor도 ν•„μš”ν•˜λ‹€. 

μš°λ¦¬κ°€ μžλ™ ν”„λ‘μ‹œ 생성기λ₯Ό μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ”, μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ”μ˜ λŒ€μƒμ΄ λ˜λŠ” λΉˆμ„ ν”„λ‘μ‹œλ‘œ κ΅μ²΄ν•˜κΈ° μœ„ν•¨μ΄λ―€λ‘œ, λŒ€μƒ 객체(target)에 ν•΄λ‹Ήλ˜λŠ” μš”μ†ŒλŠ” μ€€λΉ„κ°€ 된 μƒνƒœλ‹€. 이제 Advisor κ°€ ν•„μš”ν•œλ°, ν”„λ‘œμ νŠΈ μ½”λ“œ μ–΄λ”˜κ°€μ— Advisor κ°€ μ‘΄μž¬ν•˜λ©΄,  <code> κ°€ μžλ™μœΌλ‘œ 이λ₯Ό μ°Ύμ•„ ν”„λ‘μ‹œ νŒ©ν† λ¦¬μ— μ μš©ν•΄μ€€λ‹€κ³  λ³Ό 수 μžˆλ‹€. 

 

μžλ™ ν”„λ‘μ‹œ 생성기 μž‘λ™ κ³Όμ •

  1. 생성 : μŠ€ν”„λ§μ΄ μŠ€ν”„λ§ 빈 λŒ€μƒμ΄ λ˜λŠ” 객체λ₯Ό μƒμ„±ν•œλ‹€. 
  2. 전달 : μƒμ„±λœ 객체λ₯Ό μŠ€ν”„λ§ 빈으둜 λ“±λ‘ν•˜κΈ° 전에 빈 ν›„μ²˜λ¦¬κΈ°μ— μ „λ‹¬ν•œλ‹€. 
  3. λͺ¨λ“  Advisor 쑰회 : μžλ™ ν”„λ‘μ‹œ 생성기 - 빈 ν›„μ²˜λ¦¬κΈ° λŠ” μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ—μ„œ λͺ¨λ“  Advisor λ₯Ό μ‘°νšŒν•œλ‹€.
  4. ν”„λ‘μ‹œ 적용 λŒ€μƒ 체크 : μ‘°νšŒν•œ Advisor 의 ν¬μΈνŠΈμ»·μ„ μ‚¬μš©ν•΄ νƒ€κ²Ÿ 객체가 ν”„λ‘μ‹œ 적용 λŒ€μƒμΈμ§€ νŒλ‹¨ν•œλ‹€. ν•΄λ‹Ή 객체의 λͺ¨λ“  λ©”μ„œλ“œλ₯Ό ν¬μΈνŠΈμ»·μ— ν•˜λ‚˜ν•˜λ‚˜ 맀칭해본닀. ν•˜λ‚˜λΌλ„ 쑰건에 λ§Œμ‘±ν•˜λ©΄ ν”„λ‘μ‹œ 적용 λŒ€μƒμ΄ 돼 ν”„λ‘μ‹œ 객체가 μƒμ„±λœλ‹€. 즉 10개의 λ©”μ„œλ“œλ₯Ό 가진 κ°μ²΄μ—μ„œ ν¬μΈνŠΈμ»·μ— λ§€μΉ­λ˜λŠ” λ©”μ„œλ“œκ°€ ν•˜λ‚˜ 뿐일지라도 ν”„λ‘μ‹œ 적용 λŒ€μƒμ΄ λ˜λŠ” 것이닀.
  5. ν”„λ‘μ‹œ 생성 : ν”„λ‘μ‹œ 적용 λŒ€μƒμ΄λ©΄ ν”„λ‘μ‹œ 객체λ₯Ό 생성해 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— λ“±λ‘ν•œλ‹€. 그렇지 μ•Šλ‹€λ©΄ 원본 객체λ₯Ό μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— κ·ΈλŒ€λ‘œ λ“±λ‘ν•œλ‹€.
  6. 빈 등둝 : λ°˜ν™˜λœ κ°μ²΄λŠ” μŠ€ν”„λ§ 빈으둜 λ“±λ‘ν•œλ‹€. 

 

μ‹€μ œ 적용 μ½”λ“œ - AspectJExpressionPointcut

λˆˆμ— λ„κ²Œ μ½”λ“œλŸ‰μ΄ 쀄어든 것을 λ³Ό 수 μžˆλŠ”λ°, 빈 ν›„μ²˜λ¦¬κΈ° 자체(AnnotationAwareAspectJAutoProxyCreator)κ°€ μŠ€ν”„λ§μ— μ˜ν•΄ μžλ™μœΌλ‘œ 등둝됐기 λ•Œλ¬Έμ΄λ‹€. 

@Configuration
@Import({AppV1Config.class, AppV2Config.class})
public class AutoProxyConfig {

    @Bean
    public Advisor advisor(LogTrace logTrace) {
    
        //pointcut
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* hello.proxy.app..*(..)) 
                               && !execution(* hello.proxy.app..noLog(..))");
        
        //advice
        LogTraceAdvice advice = new LogTraceAdvice(logTrace);
        return new DefaultPointcutAdvisor(pointcut, advice);
    }

}

 

ν”„λ‘μ‹œλŠ” ν•˜λ‚˜λ§Œ μƒμ„±λœλ‹€.

μŠ€ν”„λ§λΉˆμ΄ Advisor1, Advisor2 κ°€ μ œκ³΅ν•˜λŠ” 포인트컷의 쑰건을 λͺ¨λ‘ λ§Œμ‘±ν•˜λ©΄ ν”„λ‘μ‹œ μžλ™ μƒμ„±κΈ°λŠ” ν”„λ‘μ‹œλ₯Ό λͺ‡κ°œ μƒμ„±ν• κΉŒ? 포인트컷 쑰건을 λ§Œμ‘±ν•˜λŠ” κ°μ²΄λ§ˆλ‹€ ν”„λ‘μ‹œλ₯Ό μƒμ„±ν• κΉŒ? 그렇지 μ•Šλ‹€. ν”„λ‘μ‹œ μžλ™ μƒμ„±κΈ°λŠ” ν”„λ‘μ‹œλ₯Ό ν•˜λ‚˜λ§Œ μƒμ„±ν•œλ‹€. μ™œλƒν•˜λ©΄ ν”„λ‘μ‹œ νŒ©ν† λ¦¬κ°€ μƒμ„±ν•˜λŠ” ν”„λ‘μ‹œλŠ” 내뢀에 μ—¬λŸ¬ advisor λ₯Ό 포함할 수 있기 λ•Œλ¬Έμ΄λ‹€. λ”°λΌμ„œ ν”„λ‘μ‹œλ₯Ό μ—¬λŸ¬ 개 μƒμ„±ν•΄μ„œ λΉ„μš©μ„ λ‚­λΉ„ν•  μ΄μœ κ°€ μ—†λ‹€. 

즉, Proxy λŠ” ν•˜λ‚˜λ§Œ 생성될 뿐이고 μ—¬λŸ¬ μ–΄λ“œλ°”μ΄μ €κ°€ λ“€μ–΄κ°ˆ 뿐이닀. 

 

 

정리

빈 ν›„μ²˜λ¦¬κΈ°λŠ” BeanPostProcessor μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ—¬, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— λ“±λ‘λ˜κΈ° 직전에 λΉˆμ„ μ‘°μž‘ν•  수 μžˆλ‹€. μ΄λ ‡κ²Œ 빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό μ‚¬μš©ν•˜λ©΄ μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ”μœΌλ‘œ μ»¨ν…Œμ΄λ„ˆμ— μžλ™μœΌλ‘œ λ“±λ‘λ˜λŠ” λΉˆμ— λŒ€ν•΄μ„œλ„ ν”„λ‘μ‹œ 객체λ₯Ό 생성할 수 μžˆλ‹€.

λ˜ν•œ AutoProxyCreator λ₯Ό μ‚¬μš©ν•˜λ©΄, 직접 BeanPostProcessor λ₯Ό κ΅¬ν˜„κ³Όμ •μ„ μƒλž΅ν•˜κ³ , νŽΈλ¦¬ν•˜κ²Œ ν”„λ‘μ‹œ 생성기λ₯Ό λ§Œλ“€ 수 μžˆλ‹€. κ°œλ°œμžλŠ” Advisor 만 μ€€λΉ„ν•˜λ©΄ ν”„λ‘μ‹œλ₯Ό μ†μ‰½κ²Œ 생성할 수 있게 λœλ‹€. 

 

μ½”λ“œ 및 자료 좜처

 

μŠ€ν”„λ§ 핡심 원리 - κ³ κΈ‰νŽΈ - μΈν”„λŸ° | κ°•μ˜

μŠ€ν”„λ§μ˜ 핡심 원리와 κ³ κΈ‰ κΈ°μˆ λ“€μ„ 깊이있게 ν•™μŠ΅ν•˜κ³ , μŠ€ν”„λ§μ„ μžμ‹ μžˆκ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€., - κ°•μ˜ μ†Œκ°œ | μΈν”„λŸ°...

www.inflearn.com