Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: proxy factory bean 을 사용하고 util화 한다. #23

Merged
merged 5 commits into from
Jan 13, 2023

Conversation

leo0842
Copy link
Contributor

@leo0842 leo0842 commented Jan 10, 2023

closed #13, #14

배경 지식

AOP 를 이용하기 위해 proxy 객체를 생성하는 방식에는 두 가지가 있다.

JDK Dynamic Proxy

리플렉션을 이용하여 프록시 객체를 만들고 인터페이스 구현으로 프록시 객체가 동작하게 한다.
이용하기 쉽지만 단점이 많이 존재한다.

  • 리플렉션을 사용해서 무겁고 느리다.
  • 인터페이스가 강제되어 프록시를 적용하고자 하는 객체에 인터페이스가 없다면 프록시를 이용할 수 없다.
  • 클래스 단위로 동작하기때문에 하나의 메서드에만 적용하고 싶어도 해당 객체의 다른 메서드를 호출할 때도 프록시 객체가 실행된다.

CGLIB

바이트 코드 조작을 통해 프록시 객체를 만들고 상속, 조합 방식으로 프록시 객체가 동작하게 한다.

  • JDK Dynamic Proxy 보다 가볍고 빠르다.
  • interface 가 없어도 이용가능하다.
  • 상속을 이용하기때문에 final class 라면 적용할 수 없다.

ProxyFactoryBean

  • 프록시 생성을 더 쉽게 해주기 위한 객체이다.
  • setProxyTargetClass 옵션으로 JDK Dynamic Proxy/CGLIB 을 선택할 수 있다.

상세 내용

리플렉션과 spring aop 로 분산되어 있던 프록시 생성 로직을 ProxyFactoryBean 으로 통일시켰다.

    public static Object createObject(Object target, boolean setProxyTargetClass, PointcutAdvisor advisor) {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        proxyFactoryBean.setTarget(target);
        proxyFactoryBean.setProxyTargetClass(setProxyTargetClass);
        proxyFactoryBean.addAdvisor(advisor);
        return proxyFactoryBean.getObject();
    }

target 클래스에 대해 프록시 객체를 생성한다. setProxyTargetClass 로 프록시 객체를 JDK Dynamic Proxy 로 할 것인지 CGLIB 으로 할 것인지 판단할 수 있다.

    @Around("execution(* javax.sql.DataSource.getConnection())")
    public Object datasource(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object returnValue = proceedingJoinPoint.proceed();
        ConnectionAdvisor advisor = new ConnectionAdvisor(new ConnectionPointcut(),
                new ConnectionAdvice(queryMonitor, accumulator));
        return ProxyFactoryBeanUtils.createObject(returnValue, false, advisor);
    }

DataSource 의 getConnection 메서드가 호출되면 먼저 returnValue 로 target 클래스를 응답받고, target 클래스에 대한 프록시 객체를 생성하여 반환한다.

public class ConnectionAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object returnValue = invocation.proceed();
        queryMonitor.setQuery((String) invocation.getArguments()[0]);
        StatementAdvisor advisor = new StatementAdvisor(new StatementPointcut(),
                new StatementAdvice(queryMonitor, accumulator));
        return ProxyFactoryBeanUtils.createObject(returnValue, false, advisor);
    }
}

프록시 객체는 connection 객체의 메서드를 호출하면 pointcut 으로 AOP 를 적용할 메서드를 확인하고 맞으면 위의 invoke 내부의 메서드를 실행한다.

@leo0842 leo0842 self-assigned this Jan 10, 2023
Copy link
Contributor

@cjlee38 cjlee38 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다~ ProxyFactoryBeanUtils 에 대한 테스트만 만들어주시면 저는 merge해도 될 것 같다고 생각이 드네용

Copy link
Collaborator

@Seungpang Seungpang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!
테스트도 꼼꼼하게 짜주셨네요
사용하지 않는 import만 제거해주시면 될거같아요 :)

@@ -0,0 +1,19 @@
package com.morak.performancetracker.aop.util;

import java.lang.reflect.Proxy;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용하지 않는 Import네요!

@leo0842 leo0842 changed the title proxy factory bean 을 사용하고 util화 한다. refactor: proxy factory bean 을 사용하고 util화 한다. Jan 13, 2023
@leo0842 leo0842 merged commit 06ceafb into master Jan 13, 2023
@leo0842 leo0842 deleted the refactor/using-proxy-factory-bean-#13 branch January 13, 2023 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

query AOP 를 ProxyFactoryBean 으로 전환한다.
3 participants