728x90
반응형
2022.09.30 - [프로그래밍 노트/SPRING] - [Spring] 프록시팩토리_2 (feat. Advisor)
2022.09.28 - [프로그래밍 노트/SPRING] - [Spring] 프록시팩토리_1 (feat. Advice)
프록시 팩토리는 스프링에서 제공해주는 강력한 기술이지만, 부가기능이 필요할때 마다 프록시팩토리를 사용하여 프록시 객체를 만들기에는 한계가 있다. if, 100개의 프록시 빈을 생성해야한다면? .. 설정파일에 빈들을 하나씩 추가해줘야 한다. 빈 후처리기를 활용하면 컴포넌트 스캔을 통하여 일괄로 빈을 등록할 수 있게 되는데 일단 빈 후처리기에 대해 알아보자.
빈 후처리 - BeanPostProcessor
스프링은 bean 으로 등록될 대상 객체를 찾아서(@Bean 또는 컴포넌트 스캔) 생성하고 스프링 컨테이너 내부 빈 저장소에 빈을 등록한다. 그리고 이후에 등록한 스프링 빈을 조회하여 사용하게 된다.
빈 후처리기는 스프링이 빈 저장소에 등록하기 직전에 빈을 조작할 수 있게 해준다.
이렇게되면 100개의 빈을 컴포넌트 스캔으로 생성하고, 내부 저장소에 저장되기전 후처리기를 통하여 일괄로 프록시 객체를 생성할 수 있게 되지 않을까?
빈 후처리기는 빈을 조작하고 변경할 수 있는 후킹 포인트이다.
스프링은 CommonAnnotationBeanPostProcessor 라는 빈 후처리기를 자동으로 등록하는데, 여기에서 @PostConstruct 애노테이션이 붙은 메서드를 호출한다. @PostConstruct - 스프링 빈 생성 이후에 빈을 초기화 하는 역할
빈 후처리기를 사용하여 Proxy 객체 만들기
BeanPostProcessor 구현체
@Slf4j
@RequiredArgsConstructor
public class TimeLogProxyProstProcessor implements BeanPostProcessor {
private final String basePackage;
private final Advisor advisor;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
log.info("bean : {}, beanName : {}", bean, beanName);
// 프록시 적용 대상 여부 체크
String packageName = bean.getClass().getPackageName();
if (!packageName.startsWith(basePackage)) {
return bean;
}
// 프록시 생성
ProxyFactory proxyFactory = new ProxyFactory(bean);
proxyFactory.addAdvisor(advisor);
Object proxy = proxyFactory.getProxy();
log.info("target : {}, proxy : {}", bean.getClass(), proxy.getClass());
return proxy;
}
}
BeanPostConfiguration
@Slf4j
@TestConfiguration
public class BeanPostConfiguration {
@Bean(name = "cat")
public Animal cat() {
return new Cat();
}
@Bean
public TimeLogProxyProstProcessor proxyProstProcessor() {
// beanPostProcessor 를 등록한다.
// hello.proxy 하위 패키지에 있는 bean들에 해당 Advisor를 추가하기 위함
Advisor advisor = new DefaultPointcutAdvisor(Pointcut.TRUE, new TimeAdvice());
return new TimeLogProxyProstProcessor("hello.proxy", advisor);
}
}
테스트 코드
@Slf4j
class BeanPostConfigurationTest {
@Test
void beanPostConfigTest() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanPostConfiguration.class);
Animal cat = (Animal)applicationContext.getBean("cat");
cat.bark();
}
}
TimeLogProxyProstProcessor - bean : hello.proxy.jdkdynamic.code.Cat@2970a5bc, beanName : cat
TimeLogProxyProstProcessor - target : class hello.proxy.jdkdynamic.code.Cat, proxy : class com.sun.proxy.$Proxy21
TimeAdvice - TimeProxy 실행
TimeAdvice - TimeProxy 종료 resultTime=1
부가 기능이 잘 적용된 것을 확인할 수 있다.
스프링이 제공하는 빈 후처리기
implementation 'org.springframework.boot:spring-boot-starter-aop'
- aspectjweaver라는 aspectJ 관련 라이브러리가 등록된다.
- 스프링 부트가 AOP 관련 클래스를 자동으로 스프링 빈에 등록한다.
자동 프록시 생성기 - AutoProxyCreator
- 스프링 부트 자동 설정으로
AnnotationAwareAspectJAutoProxyCreator
라는 빈 후처리기가 자동으로 등록된다. - 이 후처리기는 스프링 빈으로 등록된 Advisor 들을 자동으로 찾아서 프록시를 적용해준다.
- Advisor 안에는
Pointcut
이 있으므로, 어떤 스프링 빈에 프록시를 적용할지 알고 있다. Pointcut 에 명시된 빈들에 Advice 를 적용하여 Proxy 객체를 생성한다.
AspectJExpressionPointcut
- AspectJ라는 AOP 특화된 포인트 컷 표현식을 적용할 수 있다. 복잡한 포인트 컷을 만들 수 있다.
- 패키지뿐만 아니라 메서드 지정까지 아주 정밀하게 컨트롤할 수 있다.
@Bean
public Advisor advisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* hello.proxy.app..*(..))";
TimeAdvice advice = new TimeAdvice();
return new DefaultPointcutAdvisor(pointcut, advice);
}
- hello.proxy.app 패키지와 하위 패키지의 모든 메서드에 프록시를 자동으로 적용해준다.
- AnnotationAwareAspectJAutoProxyCreator 빈 후처리기가 말이다..
Aspect, AOP 에 대한 디테일한 내용은 다음에 알아보도록 하자
내용) 스프링 핵심 원리 - 고급편 (김영한님)
728x90
반응형
'프로그래밍 노트 > SPRING' 카테고리의 다른 글
[Spring] Spring AOP (1) | 2022.10.28 |
---|---|
[Spring] @Aspect AOP (0) | 2022.10.11 |
[Spring] 프록시팩토리_2 (feat. Advisor) (0) | 2022.09.30 |
[Spring] 프록시팩토리_1 (feat. Advice) (0) | 2022.09.28 |
[Spring] 동적 프록시 기술(feat. 리플렉션) (0) | 2022.09.27 |