π‘ κΉμνλμ μ€νλ§ ν΅μ¬ μ리 κ³ κΈνΈ κ°μλ₯Ό λ£κ³ μ 리ν λ΄μ©μ λλ€.
리νλ μ
μ§μ νλ‘μ ν΄λμ€λ₯Ό λ§λ€μ΄μ κ°λ°νλ€λ©΄ νλ‘μ ν΄λμ€κ° κ°λ¦¬ν€λ λμ ν΄λμ€ μ λ§νΌ νλ‘μ ν΄λμ€λ₯Ό λ§λ€μ΄μΌ νλ€λ μ μ΄λ€.
μλ°κ° κΈ°λ³ΈμΌλ‘ μ 곡νλ JDK λμ νλ‘μ κΈ°μ μ΄λ CGLIB κ°μ νλ‘μ μμ± μ€νμμ€ κΈ°μ μ νμ©νλ©΄ νλ‘μ κ°μ²΄λ₯Ό λμ μΌλ‘ λ§λ€μ΄λΌ μ μλ€. μ½κ² μ΄μΌκΈ°ν΄μ νλ‘μ ν΄λμ€λ₯Ό κ³μ λ§λ€μ§ μμλ λλ€λ κ²μ΄λ€. νλ‘μλ₯Ό μ μ©ν μ½λλ₯Ό νλλ§ λ§λ€μ΄λκ³ λμ νλ‘μ κΈ°μ μ μ¬μ©ν΄μ νλ‘μ κ°μ²΄λ₯Ό μ°μ΄λ΄λ©΄ λλ€.
JDK λμ νλ‘μλ₯Ό μ΄ν΄νκΈ° μν΄μλ λ¨Όμ μλ°μ 리νλ μ
κΈ°μ μ μ΄ν΄ν΄μΌ νλ€.
리νλ μ
κΈ°μ μ μ¬μ©νλ©΄ ν΄λμ€λ λ©μλμ λ©νμ 보λ₯Ό λμ μΌλ‘ νλνκ³ , μ½λλ λμ μΌλ‘ νΈμΆν μ μλ€.
μμ μ½λ
@Slf4j
public class ReflectionTest {
@Test
void reflection1() throws Exception {
//ν΄λμ€ μ 보
Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");
Hello target = new Hello();
//callA λ©μλ μ 보
Method methodCallA = classHello.getMethod("callA");
Object result1 = methodCallA.invoke(target);
log.info("result1={}", result1);
//callB λ©μλ μ 보
Method methodCallB = classHello.getMethod("callB");
Object result2 = methodCallB.invoke(target);
log.info("result2={}", result2);
}
@Slf4j
static class Hello {
public String callA() {
log.info("callA");
return "A";
}
public String callB() {
log.info("callB");
return "B";
}
}
}
- Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello"): ν΄λμ€ λ©νμ 보λ₯Ό νλνλ€. μ°Έκ³ λ‘ λ΄λΆ ν΄λμ€λ ꡬλΆμ μν΄ $λ₯Ό μ¬μ©νλ€
- classHello.getMethod("call"): ν΄λΉ ν΄λμ€μ call λ©μλ λ©νμ 보λ₯Ό νλνλ€.
- methodCallA.invoke(target): νλν λ©μλ λ©νμ λ³΄λ‘ μ€μ μΈμ€ν΄μ€μ λ©μλλ₯Ό νΈμΆνλ€. μ¬κΈ°μ methodCallAλ Hello ν΄λμ€μ callA()μ΄λΌλ λ©μλ λ©νμ 보μ΄λ€. methodCallA.invoke(μΈμ€ν΄μ€)λ₯Ό νΈμΆνλ©΄μ μΈμ€ν΄μ€λ₯Ό λ겨주면 ν΄λΉ μΈμ€ν΄μ€μ callA() λ©μλλ₯Ό μ°Ύμμ μ€ννλ€. μ¬κΈ°μλ targetμ callA() λ©μλλ₯Ό νΈμΆνλ€.
κ·Έλ°λ° target.callA()λ target.callB() λ©μλλ₯Ό μ§μ νΈμΆνλ©΄ λμ§ μ΄λ κ² λ©μλ μ 보λ₯Ό νλν΄μ λ©μλλ₯Ό νΈμΆνλ©΄ μ΄λ€ ν¨κ³Όκ° μμκΉ? μ¬κΈ°μ μ€μν ν΅μ¬μ ν΄λμ€λ λ©μλ μ 보λ₯Ό λμ μΌλ‘ λ³κ²½ν μ μλ€λ μ μ΄λ€. κΈ°μ‘΄μ callA(), callB() λ©μλλ₯Ό μ§μ νΈμΆνλ λΆλΆμ΄ Methodλ‘ λ체λμ΄ κ³΅ν΅ λ‘μ§μ λ§λ€ μ μκ² λμλ€.
@Test
void reflection2() throws Exception {
Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");
Hello target = new Hello();
Method methodCallA = classHello.getMethod("callA");
dynamicCall(methodCallA, target);
Method methodCallB = classHello.getMethod("callB");
dynamicCall(methodCallB, target);
}
private void dynamicCall(Method method, Object target) throws Exception {
log.info("start");
Object result = method.invoke(target);
log.info("result={}", result);
}
- Method method: 첫 λ²μ§Έ νλΌλ―Έν°λ νΈμΆν λ©μλ μ λ³΄κ° λμ΄μ¨λ€. μ΄κ²μ΄ ν΅μ¬μ΄λ€. κΈ°μ‘΄μλ λ©μλ μ΄λ¦μ μ§μ νΈμΆνμ§λ§, μ΄μ λ MethodλΌλ λ©νμ 보λ₯Ό ν΅ν΄μ νΈμΆν λ©μλ μ λ³΄κ° λμ μΌλ‘ μ 곡λλ€.
- Object target: μ€μ μ€νν μΈμ€ν΄μ€ μ λ³΄κ° λμ΄μ¨λ€. νμ μ΄ Object λΌλ κ²μ μ΄λ ν μΈμ€ν΄μ€λ λ°μ μ μλ€λ λ»μ΄λ€. λ¬Όλ‘ method.invoke(target)λ₯Ό μ¬μ©ν λ νΈμΆν ν΄λμ€μ λ©μλ μ λ³΄κ° μλ‘ λ€λ₯΄λ©΄ μμΈκ° λ°μνλ€.
μ£Όμ
리νλ μ κΈ°μ μ λ°νμμ λμνκΈ° λλ¬Έμ, μ»΄νμΌ μμ μ μ€λ₯λ₯Ό μ‘μ μ μλ€. μλ₯Ό λ€μ΄μ getMethod("callA")μμ λ€μ΄κ°λ λ¬Έμλ₯Ό μ€μλ‘ getMethod("callZ")λ‘ μμ±ν΄λ μ»΄νμΌ μ€λ₯κ° λ°μνμ§ μλλ€. κ·Έλ¬λ ν΄λΉ μ½λλ₯Ό μ§μ μ€ννλ μμ μ λ°μνλ μ€λ₯μΈ λ°νμ μ€λ₯κ° λ°μνλ€. κ°μ₯ μ’μ μ€λ₯λ κ°λ°μκ° μ¦μ νμΈν μ μλ μ»΄νμΌ μ€λ₯μ΄κ³ , κ°μ₯ 무μμ΄ μ€λ₯λ μ¬μ©μκ° μ§μ μ€νν λ λ°μνλ λ°νμ μ€λ₯λ€.
JDK λμ νλ‘μ
λμ νλ‘μ κΈ°μ μ μ¬μ©νλ©΄ κ°λ°μκ° μ§μ νλ‘μ ν΄λμ€λ₯Ό λ§λ€μ§ μμλ λλ€.
μ΄λ¦ κ·Έλλ‘ νλ‘μ κ°μ²΄λ₯Ό λμ μΌλ‘ λ°νμμ κ°λ°μ λμ λ§λ€μ΄μ€λ€.
κ·Έλ¦¬κ³ λμ νλ‘μμ μνλ μ€ν λ‘μ§μ μ§μ ν μ μλ€.
JDK λμ νλ‘μλ μΈν°νμ΄μ€λ₯Ό κΈ°λ°μΌλ‘ νλ‘μλ₯Ό λμ μΌλ‘ λ§λ€μ΄μ€λ€. λ°λΌμ μΈν°νμ΄μ€κ° νμμ΄λ€.
JDK λμ νλ‘μμ μ μ©ν λ‘μ§μ InvocationHandler μΈν°νμ΄μ€λ₯Ό ꡬνν΄μ μμ±νλ©΄ λλ€.
JDK λμ νλ‘μκ° μ 곡νλ InvocationHandler
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
μ 곡λλ νλΌλ―Έν°λ λ€μκ³Ό κ°λ€.
- Object proxy: νλ‘μ μμ
- Method method: νΈμΆν λ©μλ
- Object[] args: λ©μλλ₯Ό νΈμΆν λ μ λ¬ν μΈμ
ꡬν μ½λ
@Slf4j
public class TimeInvocationHandler implements InvocationHandler {
private final Object target;
public TimeInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("TimeProxy μ€ν");
long startTime = System.currentTimeMillis();
Object result = method.invoke(target, args);
long endTime = System.currentTimeMillis();
long resultTime = endTime - startTime;
log.info("TimeProxy μ’
λ£ resultTime={}", resultTime);
return result;
}
}
- TimeInvocationHandlerμ InvocationHandler μΈν°νμ΄μ€λ₯Ό ꡬννλ€. μ΄λ κ² ν΄μ JDK λμ νλ‘μμ μ μ©ν κ³΅ν΅ λ‘μ§μ κ°λ°ν μ μλ€.
- Object target: λμ νλ‘μκ° νΈμΆν λμ
- method.invoke(target, args): 리νλ μ μ μ¬μ©ν΄μ target μΈμ€ν΄μ€μ λ©μλλ₯Ό μ€ννλ€. argsλ λ©μλ νΈμΆμ λκ²¨μ€ μΈμμ΄λ€.
μ¬μ© μμ μ½λ
@Slf4j
public class JdkDynamicProxyTest {
@Test
void dynamicA() {
AInterface target = new AImpl();
TimeInvocationHandler handler = new TimeInvocationHandler(target);
AInterface proxy = (AInterface) Proxy.newProxyInstance(AInterface.class.getClassLoader(), new Class[]{AInterface.class}, handler);
proxy.call();
log.info("targetClass={}", target.getClass());
log.info("proxyClass={}", proxy.getClass());
}
@Test
void dynamicB() {
BInterface target = new BImpl();
TimeInvocationHandler handler = new TimeInvocationHandler(target);
BInterface proxy = (BInterface) Proxy.newProxyInstance(BInterface.class.getClassLoader(), new Class[]{BInterface.class}, handler);
proxy.call();
log.info("targetClass={}", target.getClass());
log.info("proxyClass={}", proxy.getClass());
}
}
μ€ν μμ
- ν΄λΌμ΄μΈνΈλ JDK λμ νλ‘μμ call()μ μ€ννλ€.
- JDK λμ νλ‘μλ InvocationHandler.invoke()λ₯Ό νΈμΆνλ€. TimeInvocationHandlerκ° κ΅¬νμ²΄λ‘ μμΌλ―λ‘ TimeInvocationHandler.invoke()κ° νΈμΆλλ€.
- TimeInvocationHandlerκ° λ΄λΆ λ‘μ§μ μννκ³ , method.invoke(target, args)λ₯Ό νΈμΆν΄μ targetμΈ μ€μ κ°μ²΄( AImpl )λ₯Ό νΈμΆνλ€.
- AImpl μΈμ€ν΄μ€μ call()μ΄ μ€νλλ€.
- AImpl μΈμ€ν΄μ€μ call()μ μ€νμ΄ λλλ©΄ TimeInvocationHandlerλ‘ μλ΅μ΄ λμμ¨λ€. μκ° λ‘κ·Έλ₯Ό μΆλ ₯νκ³ κ²°κ³Όλ₯Ό λ°ννλ€.
JDK λμ νλ‘μ λμ μ , ν λΉκ΅
μ 리
μμ λ₯Ό 보면 AImpl, BImpl κ°κ° νλ‘μλ₯Ό λ§λ€μ§ μμλ€.
νλ‘μλ JDK λμ νλ‘μλ₯Ό μ¬μ©ν΄μ λμ μΌλ‘ λ§λ€κ³ TimeInvocationHandlerλ 곡ν΅μΌλ‘ μ¬μ©νλ€.
JDK λμ νλ‘μ κΈ°μ λλΆμ μ μ© λμ λ§νΌ νλ‘μ κ°μ²΄λ₯Ό λ§λ€μ§ μμλ λλ€.
κ·Έλ¦¬κ³ κ°μ λΆκ° κΈ°λ₯ λ‘μ§μ νλ²λ§ κ°λ°ν΄μ 곡ν΅μΌλ‘ μ μ©ν μ μλ€.
λ§μ½ μ μ© λμμ΄ 100κ°μ¬λ λμ νλ‘μλ₯Ό ν΅ν΄μ μμ±νκ³ , κ°κ° νμν InvocationHandlerλ§ λ§λ€μ΄μ λ£μ΄μ£Όλ©΄ λλ€. κ²°κ³Όμ μΌλ‘ νλ‘μ ν΄λμ€λ₯Ό μ μμ΄ λ§λ€μ΄μΌ νλ λ¬Έμ λ ν΄κ²°νκ³ , λΆκ° κΈ°λ₯ λ‘μ§λ νλμ ν΄λμ€μ λͺ¨μμ λ¨μΌ μ± μ μμΉ(SRP)λ μ§ν¬ μ μκ² λμλ€.
'Spring > AOP' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
@Aspect AOP (0) | 2024.11.12 |
---|---|
λΉ νμ²λ¦¬κΈ° (0) | 2024.11.12 |
ν¬μΈνΈμ»·, μ΄λλ°μ΄μ€, μ΄λλ°μ΄μ (0) | 2024.11.11 |
νλ‘μ ν©ν 리 (0) | 2024.11.11 |
CGLIB (0) | 2024.11.11 |