자바 동적 에이전트 (전재)

동적 대 리 는 많은 구조 와 기술 의 기초 이 고 spring 의 AOP 실현 은 동적 대 리 를 바탕 으로 이 루어 진 것 이다.동적 에이전트 의 메커니즘 을 이해 하 는 것 은 AOP 의 밑바닥 실현 을 이해 하 는 데 도움 이 된다.
       doc 문 서 를 보면 자바. lang. reflect 패키지 에 Proxy 라 는 클래스 가 있 습 니 다.다음은 doc 문서 가 Proxy 클래스 에 대한 설명 입 니 다.
       "A dynamic proxy class (simply referred to as a proxy class below) is a class that implements a list of interfaces specified at runtime when the class is created, with behavior as described below. A proxy interface is such an interface that is implemented by a proxy class. A proxy instance is an instance of a proxy class. Each proxy instance has an associated invocation handler object, which implements the interface InvocationHandler ."
        프 록 시 클래스 의 디자인 은 프 록 시 모드 의 디자인 사상 을 사용 하고 프 록 시 클래스 대상 은 프 록 시 목표 의 모든 인 터 페 이 스 를 실현 하 며 목표 대상 을 대체 하여 실제 작업 을 한다.그러나 이런 대 체 는 간단 한 대체 가 아니 라 아무런 의미 가 없다. 대리 의 목적 은 목표 대상 방법 을 바탕 으로 강화 하 는 것 이다. 이런 강화 의 본질은 보통 목표 대상 의 방법 을 차단 하 는 것 이다.따라서 프 록 시 는 차단 방법 이 호출 될 때 어떤 처 리 를 하 는 지 알려 주 는 방법 차단 기 를 포함해 야 한다.Invocation Handler 는 바로 차단기 의 인터페이스 이다.
      Invocation Handler 인터페이스 도 java. lang. reflec 에 있 습 니 다.
     Object invoke ( Object  proxy, Method  method, Object [] args)
     이 인 터 페 이 스 는 세 개의 매개 변수 가 있 는데 그 중에서 두 번 째 와 세 번 째 매개 변 수 는 모두 이해 하기 쉽다. 하 나 는 차단 되 는 방법 이 고 하 나 는 이 방법의 매개 변수 목록 이다.관건 은 첫 번 째 매개 변수 다.doc 문서 의 해석 에 따라
      proxy - the proxy instance that the method was invoked on
      즉, proxy 는 프 록 시 인 스 턴 스 여야 하 는데 왜 이 인 자 를 입력 해 야 합 니까?
      이 문 제 를 가지 고 스스로 작은 프로그램 을 만들어 약간의 실험 을 하 였 다.
///////////////////////////////////////
      public interface IAnimal {            void info();       }
////////////////////////////////////
    public class Dog implements IAnimal
    {
          public void info() {              System.out.println("I am a dog!");           }     }
/////////////////////////////////////// import java.lang.reflect.*;
public class ProxyTest {  public static void main(String[] args) throws InterruptedException {   final IAnimal animal = new Dog();   Object proxyObj =Proxy.newProxyInstance(     animal.getClass().getClassLoader(),     animal.getClass().getInterfaces(),     new InvocationHandler()     {      public Object invoke(Object proxy, Method method, Object[] args)      {       try {        System. out. println ("차단 되 는 방법:" + method. getName ());       return method.invoke(animal, args);       }       catch (IllegalArgumentException e) {        // TODO Auto-generated catch block        e.printStackTrace();        return null;       } catch (IllegalAccessException e) {        // TODO Auto-generated catch block        e.printStackTrace();        return null;       } catch (InvocationTargetException e) {        // TODO Auto-generated catch block        e.printStackTrace();        return null;       }      }     });   if(proxyObj instanceof IAnimal)   {    System.out.println("the proxyObj is an animal!");   }   else   {    System.out.println("the proxyObj isn't an animal!");   }      if(proxyObj instanceof Dog)   {    System.out.println("the proxyObj is a dog!");   }   else   {    System.out.println("the proxyObj isn't a dog!");   }      IAnimal animalProxy = (IAnimal)proxyObj;   animalProxy.info();   animalProxy.hashCode();   System.out.println(animalProxy.getClass().getName().toString());  } }
프로그램 실행 결 과 는 다음 과 같 습 니 다.
the proxyObj is an animal! the proxyObj isn 't a dog! 차단 되 는 방법: info I am a dog! 차단 되 는 방법: hashCode $Proxy 0
결 과 를 보면 다음 과 같은 몇 가 지 를 알 수 있다.
1. proxy Obj 는 목표 대상 인 터 페 이 스 를 실현 하 는 대상 이지 목표 대상 과 다르다. 즉, 이러한 대리 체 제 는 인 터 페 이 스 를 대상 으로 하 는 것 이지 유형 을 대상 으로 하 는 것 이 아니다.
2. info 방법 (인터페이스 에서) 이 성공 적 으로 차단 되 었 습 니 다. hashCode 방법 도 성공 적 으로 차단 되 었 습 니 다. 그러나 의외로 getClass 방법 (Object 류 를 계승 하 는 방법) 은 차단 되 지 않 았 습 니 다!
3. 디 버 깅 을 사용 하면 Invocation 인터페이스 에서 invoke 방법 으로 들 어 오 는 proxy 매개 변 수 는 프 록 시 대상 인 스 턴 스 proxy Obj 임 을 알 수 있 습 니 다.
왜 getClass () 가 차단 되 지 않 았 습 니까? proxy 인 자 는 무슨 소 용이 있 습 니까?
우선, 시험 해 보 세 요. 이 proxy 매개 변 수 는 프 록 시 인 스 턴 스 대상 이 므 로 당연히 proxy Obj 와 같 습 니 다. info 등 방법 을 호출 할 수 있 습 니 다. 따라서 invoke 방법 에 다음 과 같은 문 구 를 추가 할 수 있 습 니 다.
((IAnimal)proxy).info();
결 과 는:
the proxyObj is an animal! the proxyObj isn 't a dog! 차단 되 는 방법: info 차단 되 는 방법: info
.......
차단 방법: info 차단 방법: info
그 다음 에 창고 가 넘 쳐 요.
결 과 는 분명 합 니 다. invoke 방법 에서 proxy 를 호출 하 는 방법 은 다시 invoke 방법 을 일 으 킬 수 있 습 니 다. 이것 은 순환 에 빠 졌 습 니 다. 최종 결 과 는 당연히 스 택 이 넘 쳤 습 니 다.
invoke 방법 에서 proxy. getClass () 를 호출 할 수 있 습 니 다. 프로그램 은 정상적으로 실 행 될 수 있 습 니 다. 그러나 hashCode () 방법 을 호출 하면 스 택 이 넘 칠 수 있 습 니 다.
       위의 시험 을 통 해 invoke 인터페이스 에 있 는 proxy 인 자 는 실 현 된 인 터 페 이 스 를 호출 하 는 방법 에 사용 할 수 없다 는 초보적인 결론 을 얻 을 수 있 습 니 다. 이상 한 것 은 hashCode () 와 getClass () 방법 은 모두 Object 에서 계승 하 는 방법 입 니 다. 왜 하 나 는 다른 것 으로 할 수 있 습 니까? 첫 번 째 의문 을 가지 고 doc 문서 에 가서 Object 의 이 두 가지 방법 을 살 펴 보 니 getClass () 를 발견 하 였 습 니 다.final 로 정의 되 어 있 습 니 다. hashCode () 는 아 닙 니 다. 이 때 문 입 니까? equals 가 시도 하면 스 택 이 넘 칠 수 있 습 니 다. wait () 와 같은 다른 final 방법 을 찾 아 보 았 습 니 다. invoke 는 차단 하지 않 았 습 니 다. final 이 관건 입 니까?
      또 하나의 문 제 는 proxy 가 무슨 소 용이 있 습 니까? proxy 가 getClass () 를 호출 할 수 있 으 니방법, 우 리 는 proxy 의 Class 클래스 이미 지 를 얻 을 수 있 습 니 다. 예 를 들 어 proxy 프 록 시 인 스 턴 스 에 관 한 모든 종류의 정 보 를 얻 을 수 있 습 니 다. 예 를 들 어 방법 목록, Annotation 등 은 우리 에 게 proxy 를 분석 하 는 유력 한 도구 입 니 다. 예 를 들 어 Annotation 분석 방법 을 분석 하 는 성명 식 사무 수 요 를 통 해 proxy 인 자 를 전달 하 는 것 이 이러한 의도 라 고 생각 합 니 다.
 
Invocation Handler 의 자료
패키지: java. lang. reflect
public interface InvocationHandler
InvocationHandler 프 록 시 인 스 턴 스 호출 처리 프로그램 이 실현 하 는 인터페이스 입 니 다.
모든 코드 인 스 턴 스 는 하나의 호출 처리 프로그램 을 가지 고 있 습 니 다. 프 록 시 인 스 턴 스 호출 방법 을 사용 할 때 방법 호출 을 인 코딩 하고 호출 처리 프로그램 invoke 에 할당 합 니 다.
다음 버 전부터:
JDK1.3
invoke
Object
 invoke
(Object
 proxy,

Method  method,

Object [] args)

throws Throwable

프 록 시 인 스 턴 스 에서 방법 을 호출 하고 결 과 를 되 돌려 줍 니 다. 방법 과 연 결 된 프 록 시 인 스 턴 스 에서 방법 을 호출 할 때 호출 처리 프로그램 에서 이 방법 을 호출 합 니 다.
 
인자:proxy - 그 위 에서 호출 하 는 방법의 에이전트 인 스 턴 스method - 프 록 시 인 스 턴 스 에서 호출 되 는 인터페이스 방법 에 대응 하 는Method 실례.Method 대상 의 성명 류 는 그 중에서 성명 방법의 인터페이스 가 될 것 이다. 이 인 터 페 이 스 는 대리 류 가 계승 방법 을 가 진 대리 인터페이스의 초 인터페이스 일 수 있다.args - 프 록 시 인 스 턴 스 에 호출 되 는 매개 변수 값 을 포함 하 는 대상 배열 입 니 다. 인터페이스 방법 이 파 라 메 터 를 사용 하지 않 으 면...null. 기본 유형의 매개 변 수 는 적당 한 기본 포장 기 류 에 포장 된다 (예 를 들 어java.lang.Integer 또는java.lang.Boolean 의 실례 중.
돌아 가기:
프 록 시 인 스 턴 스 의 방법 에서 되 돌아 오 는 값 을 호출 합 니 다. 인터페이스 방법의 성명 반환 형식 이 기본 형식 이 라면 이 방법 이 되 돌아 오 는 값 은 기본 포장 대상 클래스 의 인 스 턴 스 입 니 다. 그렇지 않 으 면 설명 반환 형식 으로 분 배 될 수 있 습 니 다. 이 방법 이 되 돌아 오 는 값 은 다음 과 같 습 니 다.null 또한 인터페이스 방법의 반환 유형 은 기본 유형 이 고 대리 인 스 턴 스 의 방법 호출 은 던 집 니 다.NullPointerException. 그렇지 않 으 면 이 방법 이 되 돌아 오 는 값 이 상기 인터페이스 방법의 성명 반환 형식 과 호 환 되 지 않 으 면 프 록 시 인 스 턴 스 의 방법 호출 을 던 집 니 다.ClassCastException
던 지기:Throwable - 프 록 시 인 스 턴 스 의 방법 에서 던 진 이상 을 호출 합 니 다. 이 이상 한 유형 은 인터페이스 방법 에 할당 할 수 있어 야 합 니 다.throws 자구 에 명 시 된 이상 유형 이나 검사 되 지 않 은 이상 유형java.lang.RuntimeException 또는java.lang.Error. 이 방법 이 검 사 를 거 친 이상 을 던 지면 인터페이스 방법 에 할당 할 수 없습니다.throws 자구 에서 설명 한 모든 이상 유형, 에이전트 인 스 턴 스 방법 호출 은 이 방법 을 포함 하여 던 진 이상 한 것 을 던 집 니 다.UndeclaredThrowableException

좋은 웹페이지 즐겨찾기