자바 동적 에이전트 분석

자바 동적 에이전트 분석
동적 대 리 는 바이트 코드 강화 기술 로 서 SpringAOP 의 핵심 으로 이 루어 집 니 다.우 리 는 이 를 사용 하 는 동시에'그 이 유 를 알 고 그 이 유 를 아 는 것'을 잘 하 는 것 이 좋 습 니 다.
동적 에이전트 demo대리 류
총화
1.동적 에이전트 데모
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/** * author : * date : 16/4/20. * describe : */
public class MyInvokeHandler implements InvocationHandler {

    private Object target;

    public MyInvokeHandler(Object target){
        super();
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object o = method.invoke(target,args);
        System.out.println("after");
        return o;
    }

    /*** *      * @return *  newProxyInstance           ,                  ,                 ,                                  。 */
    public Object getProxy(){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this);
    }
}
public interface Service {
    public String info();
}

public class MyService implements Service {
    @Override
    public String info() {
        return "hello";
    }

    public static void main(String[] args) {
        MyInvokeHandler handler = new MyInvokeHandler(new MyService());
        Service service = (Service)handler.getProxy();
        //         
        byte[] clazz = ProxyGenerator.generateProxyClass("$Proxy1",MyService.class.getInterfaces());
        FileOutputStream out = null;
        try {
            out = new FileOutputStream("/Users/admin/Desktop/$Proxy1.class");
            out.write(clazz);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        service.info();
    }
}

실행 결과:
before
after

이상 의 작은 demo 를 통 해 알 수 있 듯 이 동적 에이전트 의 최종 실현 효 과 는 대리 의 실행 과정 전후 에 일부 처리 논 리 를 추가 할 수 있 습 니 다.예 를 들 어 demo 에서 일부 문자열 을 인쇄 한 것 과 같 습 니 다.물론 동적 에이전트 의 기능 은 크게 다 릅 니 다.우 리 는 호출 전후 로 그 를 인쇄 하고 사 무 를 제어 하 며 강화 방법 등 을 사용 하여 소스 코드 를 수정 하지 않 은 상태 에서 우리 가 필요 로 하 는 기능 을 추가 할 수 있 습 니 다.
위의 demo 는 동적 대 리 를 어떻게 사용 하 는 지 간단하게 소개 했다.생 성 된 대리 류 의 내용 이 무엇 인지 살 펴 보 자.
2.프 록 시 클래스
같은 인터페이스 에 있어 서 현 류 는 대리 류 와 관련 이 있다.우 리 는 위 에서 프 록 시 클래스 의 바이트 코드 를 파일 에 기 록 했 습 니 다.여러분 은 역 컴 파일 한 후에 그 내용 을 다음 과 같이 볼 수 있 습 니 다.
//           extends        ,              Proxy, java      
public final class $Proxy1 extends Proxy implements Service {
  //4 Method         4   。
  private static Method m1;
  private static Method m3;
  private static Method m2;
  private static Method m0;

  public $Proxy1(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

//         ,         InvocationHandler     invoke  。      invoke            。
  public final String info()
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m3, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String toString()
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  static
  {
    try
    {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("com.service.util.property.Service").getMethod("info", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

3.총화
1.동적 대 리 는 jvm 이 실 행 된 후에 메모리 에 class 를 생 성하 여 원래 가지 고 있 지 않 은 기능 을 강화 하 는 데 사용 되 지만 원래 의 클래스 도 없어 서 는 안 되 거나 없어 서 는 안 된다.왜냐하면 진정한 핵심 논 리 는 원래 의 클래스 에 있 기 때문이다.2.프 록 시 클래스 가 메모리 에 존재 하 는 방식 은 기본적으로 프 록 시 를 계승 하 는 동시에 우리 가 들 어 오 는 인 터 페 이 스 를 실현 합 니 다.실행 할 때 동적 으로 생 성 된 대상 이 고 이름 을 짓 는 방식 은 모두 이러한 형식 입 니 다.$로 시작 하고 프 록 시 를 중심 으로 마지막 숫자 는 대상 의 레이 블 을 표시 합 니 다.3.프 록 시 클래스 는 기본적으로 hashCode(),equals(),toString(),그리고 계승 하 는 인터페이스 에 필요 한 방법 을 실현 하기 때문에 proxy.getClass().getName()과 유사 한 프 록 시 클래스 의 클래스 를 호출 할 때 프 록 시 클래스 의 클래스 이름 을 얻 지 못 합 니 다.

좋은 웹페이지 즐겨찾기