java에서 동적 에이전트의 실현

동적 에이전트의 실현
사용 모드: 프록시 모드.
프록시 모드의 역할은 이 대상에 대한 접근을 제어하기 위해 다른 대상에 에이전트를 제공하는 것이다.셋방 같은 중개업자.
두 가지 동적 에이전트:
(1) jdk 동적 에이전트, jdk 동적 에이전트는 자바 내부의 반사 메커니즘으로 이루어진 것으로 목표 클래스는 통일된 인터페이스를 바탕으로 한다(InvocationHandler)
(2) cglib 동적 에이전트, cglib 동적 에이전트의 밑바닥은 asm를 빌려 실현된 것이다. cglib와 같은 제3자 라이브러리에서 실현된 동적 에이전트의 응용은 더욱 광범위하고 효율에 있어 더욱 유리하다.
기본 적용 프레임워크:
Spring의 AOP, Struts2의 차단기
구현:
1. 인터페이스와 실현 클래스 정의

package com.example.service;
public interface UserService {
  public String getName(int id);
  public Integer getAge(int id);
}

package com.example.service.impl;
import com.example.service.UserService;
public class UserServiceImpl implements UserService {
  public String getName(int id) {
    System.out.println("------getName------");
    return "cat";
  }
  public Integer getAge(int id) {
    System.out.println("------getAge------");
    return 10;
  }
}
2. jdk 동적 에이전트 구현

package com.example.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyInvocationHandler implements InvocationHandler {
  private Object target;
  /**
   *  
   *
   * @param target
   * @return
   */
  public Object bind(Object target) {
    this.target = target;
    // 
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
        target.getClass().getInterfaces(), this);  // ( ,cglib )
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if ("getName".equals(method.getName())) {
      System.out.println("------before " + method.getName() + "------");
      Object result = method.invoke(target, args);
      System.out.println("------after " + method.getName() + "------");
      return result;
    } else {
      Object result = method.invoke(target, args);
      return result;
    }
  }
}

package com.example.jdk;

import com.example.service.UserService;
import com.example.service.impl.UserServiceImpl;

/**
 *  
 */
public class RunJDK {
  public static void main(String[] args) {
    MyInvocationHandler proxy = new MyInvocationHandler();
    UserService userServiceProxy = (UserService) proxy.bind(new UserServiceImpl());
    System.out.println(userServiceProxy.getName(1));
    System.out.println(userServiceProxy.getAge(1));
  }
}
실행 결과:
------before getName------
------getName------
------after getName------
cat
------getAge------

3. cglib 동적 에이전트 구현:
JDK의 동적 에이전트 메커니즘은 에이전트만 인터페이스의 클래스를 실현할 수 있고 인터페이스를 실현하지 못하는 클래스는 JDK의 동적 에이전트를 실현할 수 없다. cglib는 클래스를 대상으로 에이전트를 실현한다. 그의 원리는 지정한 목표 클래스에 대해 하위 클래스를 생성하고 그 중에서 덮어쓰는 방법으로 강화를 실현하지만 계승하기 때문에final 수식 클래스에 대해 에이전트를 할 수 없다.
CGLIB의 핵심 클래스:
net.sf.cglib.proxy.Enhancer C의 주요 개선 사항
net.sf.cglib.proxy.MethodInterceptor C의 주요 방법 차단 클래스입니다. 이것은 Callback 인터페이스의 하위 인터페이스입니다. 사용자가 실현해야 합니다.
net.sf.cglib.proxy.MethodProxy C JDK의 java.lang.reflect.Method 클래스의 프록시 클래스는 원본 대상 방법의 호출을 편리하게 실현할 수 있습니다.
net.sf.cglib.proxy.MethodInterceptor 인터페이스는 가장 일반적인 콜백 (callback) 형식으로 에이전트 기반의 AOP에서 차단 (intercept) 방법을 호출하는 데 자주 사용된다.이 인터페이스는 단지 하나의 방법만 정의했다
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;
첫 번째 파라미터는 에이전트 이미지이고, 두 번째와 세 번째 파라미터는 각각 차단하는 방법과 방법의 파라미터이다.원래의 방법은java를 사용할 수 있습니다.lang.reflect.Method 대상의 일반 반사 호출이나net을 사용합니다.sf.cglib.proxy.MethodProxy 객체 호출.net.sf.cglib.proxy.MethodProxy는 일반적으로 더 빠르기 때문에 가장 먼저 사용됩니다.

package com.example.cglib;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGLIBProxy implements MethodInterceptor {
  private Object target;
  /**
   *  
   *
   * @param target
   * @return
   */
  public Object getInstance(Object target) {
    this.target = target;
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(this.target.getClass());
    //  
    enhancer.setCallback(this);
    //  
    return enhancer.create();
  }
  @Override
  public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
    System.out.println(method.getName());
    Object result = methodProxy.invokeSuper(o, objects);
    System.out.println("++++++after " + methodProxy.getSuperName() + "++++++");
    return result;
  }
}

package com.example.cglib;
import com.example.service.UserService;
import com.example.service.impl.UserServiceImpl;
/**
 *  CGLIB
 */
public class RunCGLIB {
  public static void main(String[] args) {
    CGLIBProxy cglibProxy = new CGLIBProxy();
    UserService userService = (UserService) cglibProxy.getInstance(new UserServiceImpl());
    userService.getName(1);
    userService.getAge(1);
  }
}
실행 결과:
++++++before CGLIB$getName$0++++++
getName
------getName------
++++++after CGLIB$getName$0++++++
++++++before CGLIB$getAge$1++++++
getAge
------getAge------
++++++after CGLIB$getAge$1++++++
이상은 본문의 전체 내용입니다. 본고의 내용이 여러분의 학습이나 업무에 일정한 도움을 줄 수 있는 동시에 저희를 많이 지지해 주시기 바랍니다!

좋은 웹페이지 즐겨찾기