Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- jpa
- Exception
- QueryDSL
- kotlin
- pointcut
- db
- 스프링
- 인프런
- http
- springdatajpa
- JDBC
- Proxy
- 스프링 핵심 원리
- spring
- Android
- 알고리즘
- 김영한
- 스프링 핵심 기능
- Greedy
- transaction
- 자바
- Thymeleaf
- 백준
- JPQL
- 그리디
- Servlet
- AOP
- java
- Spring Boot
- SpringBoot
Archives
- Today
- Total
개발자되기 프로젝트
[빈 후처리기] 예제코드 2 - 객체 바꿔치기 본문
1. 스프링 빈 등록과정 - 바꿔치기
- 객체를 바꿔치기 한다며 빈 이름은 변경되지 않고 객체만 변경된다.
2. BeanPostProcessor Interface - 스프링 제공
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
}
- 빈 후처리기를 사용하려면 BeanPostProcessor 인터페이스를 구현하고, 스프링 빈으로 등록하면 된다.
- postProcessBeforeInitialization
- 객체 생성 이후에 @PostConstruct 같은 초기화가 발생하기 전에 호출되는 포스트 프로세서이다.
- postProcessAfterInitialization
- 객체 생성 이후에 @PostConstruct 같은 초기화가 발생한 다음에 호출되는 포스트 프로세서이다.
3.예제 코드
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
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 {
@Override
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 객체로 바꿔치기 한다.
- 파라미터로 넘어오는 빈( bean ) 객체가 A 의 인스턴스이면 새로운 B 객체를 생성해서 반환한다.
- 여기서 A 대신에 반환된 값인 B 가 스프링 컨테이너에 등록된다.
- 다음 실행결과를 보면 beanName=beanA , bean=A 객체의 인스턴스가
- 빈 후처리기에 넘어온 것을 확인할 수 있다.
- 인터페이스인 BeanPostProcessor 를 구현하고, 스프링 빈으로 등록하면
hello.proxy.postprocessor.BeanPostProcessorTest$AToBPostProcessor - beanName=beanA, bean=hello.proxy.postprocessor.BeanPostProcessorTest$A@7b84fcf8
hello.proxy.postprocessor.BeanPostProcessorTest$B - hello B
- BeanPostProcessor에 넘어온 것은 A이지만 return은 B객체가 return 되었다.
- 실행 결과를 보면 최종적으로 "beanA" 라는 스프링 빈 이름에 A 객체 대신에 B 객체가 등록된 것을
확인할 수 있다. A 는 스프링 빈으로 등록조차 되지 않는다.
4. 정리
- 빈 후처리기는 빈을 조작하고 변경할 수 있는 후킹 포인트이다.
- 이것은 빈 객체를 조작하거나 심지어 다른 객체로 바꾸어 버릴 수 있을 정도로 막강하다.
- 여기서 조작이라는 것은 해당 객체의 특정 메서드를 호출하는 것을 뜻한다.
- 일반적으로 스프링 컨테이너가 등록하는,
- 특히 컴포넌트 스캔의 대상이 되는 빈들은 중간에 조작할 방법이 없는데,
- 빈 후처리기를 사용하면 개발자가 등록하는 모든 빈을 중간에 조작할 수 있다.
- 이 말은 빈 객체를 프록시로 교체하는 것도 가능하다는 뜻이다. ㅇㅎ!
5. 참고 - @PostConstruct의 비밀
- @PostConstruct 는 스프링 빈 생성 이후에 빈을 초기화 하는 역할을 한다.
- 그런데 생각해보면 빈의 초기화 라는 것이
단순히 @PostConstruct 애노테이션이 붙은 초기화 메서드를 한번 호출만 하면 된다. - 쉽게 이야기해서 생성된 빈을 한번 조작하는 것이다.
- 따라서 빈을 조작하는 행위를 하는 적절한 빈 후처리기가 있으면 될 것 같다.
- 스프링은 CommonAnnotationBeanPostProcessor 라는 빈 후처리기를 자동으로 등록하는데,
- 여기에서 @PostConstruct 애노테이션이 붙은 메서드를 호출한다.
- 따라서 스프링 스스로도 스프링 내부의 기능을 확장하기 위해 빈 후처리기를 사용한다.
6. GitHub : 220102 Bean Post Processor 2
'인프런 > [인프런] 스프링 핵심 원리 - 고급' 카테고리의 다른 글
[빈 후처리기] 정리 (0) | 2022.01.03 |
---|---|
[빈 후처리기] Bean Post Processor 적용 (0) | 2022.01.02 |
[빈 후처리기] 예제코드 1 - 일반적인 스프링 빈 등록 (0) | 2022.01.02 |
[빈 후처리기] Bean Post Processor - 소개 (0) | 2022.01.02 |
프록시팩토리- 정리 (0) | 2022.01.01 |
Comments