>Java >java지도 시간 >Java 동적 프록시 적용에 대한 자세한 설명

Java 동적 프록시 적용에 대한 자세한 설명

黄舟
黄舟원래의
2016-12-19 14:28:421317검색

동적 프록시는 실제로 지정한 모든 인터페이스를 기반으로 클래스를 동적으로 생성하는 java.lang.reflect.Proxy 클래스입니다. 바이트이면 이 클래스는 Proxy 클래스를 상속하고 지정한 모든 인터페이스(매개변수에 전달한 인터페이스 배열)를 구현한 다음 지정한 클래스로더를 사용합니다. 수업 byte가 시스템에 로드되고 최종적으로 그러한 클래스의 객체가 생성되고 invocationHandler, 즉 모든 인터페이스에 해당하는 Method 멤버와 같은 객체의 일부 값이 초기화됩니다. 초기화 후 개체는 호출 클라이언트로 반환됩니다. 이러한 방식으로 클라이언트는 모든 인터페이스를 구현하는 프록시 개체를 얻습니다. 분석 예를 참조하세요.

package com.fans.common.proxy;
public interface BusinessProcessor {
  public void processBusiness();
}
package com.fans.common.proxy;
/**
 * 业务处理类
 * @author fanshadoop
 *
 */
public class BusinessProcessorImpl implements BusinessProcessor {
 @Override
 public void processBusiness() {
  System.out.println("processing business.....");
 }
}
package com.fans.common.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 业务代理类
 * @author fanshadoop
 *
 */
public class BusinessProcessorHandler implements InvocationHandler {
 private Object target = null;
 BusinessProcessorHandler(Object target) {
  this.target = target;
 }
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  System.out
    .println("You can do something here before process your business");
  Object result = method.invoke(target, args);
  System.out
    .println("You can do something here after process your business");
  return result;
 }
}
package com.fans.common.proxy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
public class Test {
 /**
  * @param args
  */
 public static void main(String[] args) {
  BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
  BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
  BusinessProcessor bp = (BusinessProcessor) Proxy.newProxyInstance(
    bpimpl.getClass().getClassLoader(), bpimpl.getClass()
      .getInterfaces(), handler);
  bp.processBusiness();
  System.out.println(bp.getClass().getName());
  printClassDefinition(bp.getClass());
 }
 public static String getModifier(int modifier) {
  String result = "";
  switch (modifier) {
  case Modifier.PRIVATE:
   result = "private";
  case Modifier.PUBLIC:
   result = "public";
  case Modifier.PROTECTED:
   result = "protected";
  case Modifier.ABSTRACT:
   result = "abstract";
  case Modifier.FINAL:
   result = "final";
  case Modifier.NATIVE:
   result = "native";
  case Modifier.STATIC:
   result = "static";
  case Modifier.SYNCHRONIZED:
   result = "synchronized";
  case Modifier.STRICT:
   result = "strict";
  case Modifier.TRANSIENT:
   result = "transient";
  case Modifier.VOLATILE:
   result = "volatile";
  case Modifier.INTERFACE:
   result = "interface";
  }
  return result;
 }
 public static void printClassDefinition(Class clz) {
  String clzModifier = getModifier(clz.getModifiers());
  if (clzModifier != null && !clzModifier.equals("")) {
   clzModifier = clzModifier + " ";
  }
  String superClz = clz.getSuperclass().getName();
  if (superClz != null && !superClz.equals("")) {
   superClz = "extends " + superClz;
  }
  Class[] interfaces = clz.getInterfaces();
  String inters = "";
  for (int i = 0; i < interfaces.length; i++) {
   if (i == 0) {
    inters += "implements ";
   }
   inters += interfaces[i].getName();
  }
  System.out.println(clzModifier + clz.getName() + " " + superClz + " "
    + inters);
  System.out.println("{");
  Field[] fields = clz.getDeclaredFields();
  for (int i = 0; i < fields.length; i++) {
   String modifier = getModifier(fields[i].getModifiers());
   if (modifier != null && !modifier.equals("")) {
    modifier = modifier + " ";
   }
   String fieldName = fields[i].getName();
   String fieldType = fields[i].getType().getName();
   System.out.println("    " + modifier + fieldType + " " + fieldName
     + ";");
  }
  System.out.println();
  Method[] methods = clz.getDeclaredMethods();
  for (int i = 0; i < methods.length; i++) {
   Method method = methods[i];
   String modifier = getModifier(method.getModifiers());
   if (modifier != null && !modifier.equals("")) {
    modifier = modifier + " ";
   }
   String methodName = method.getName();
   Class returnClz = method.getReturnType();
   String retrunType = returnClz.getName();
   Class[] clzs = method.getParameterTypes();
   String paraList = "(";
   for (int j = 0; j < clzs.length; j++) {
    paraList += clzs[j].getName();
    if (j != clzs.length - 1) {
     paraList += ", ";
    }
   }
   paraList += ")";
   clzs = method.getExceptionTypes();
   String exceptions = "";
   for (int j = 0; j < clzs.length; j++) {
    if (j == 0) {
     exceptions += "throws ";
    }
    exceptions += clzs[j].getName();
    if (j != clzs.length - 1) {
     exceptions += ", ";
    }
   }
   exceptions += ";";
   String methodPrototype = modifier + retrunType + " " + methodName
     + paraList + exceptions;
   System.out.println("    " + methodPrototype);
  }
  System.out.println("}");
 }
}

실행 결과:

You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
$Proxy0 extends java.lang.reflect.Proxy implements com.fans.common.proxy.BusinessProcessor
{
    java.lang.reflect.Method m1;
    java.lang.reflect.Method m3;
    java.lang.reflect.Method m0;
    java.lang.reflect.Method m2;
    boolean equals(java.lang.Object);
    java.lang.String toString();
    int hashCode();
    void processBusiness();
}

BusinessProcessorHandler 클래스는 InvocationHandler 인터페이스의 호출 메서드를 구현합니다. 최종 프록시 호출 고정 인터페이스 메소드입니다.


분명히 Proxy.newProxyInstance 메서드는 다음 작업을 수행합니다.
1. 인터페이스에서 인터페이스를 구현하기 위해 전달된 두 번째 매개변수 인터페이스를 기반으로 클래스를 동적으로 생성합니다. 이 예에서는 BusinessProcessor 인터페이스의 processBusiness 메소드입니다. 그리고 Proxy 클래스를 상속하고 hashcode, toString 및 equals와 같은 세 가지 메서드를 다시 작성합니다. 구체적인 구현에 대해서는 다음을 참조하세요. ProxyGenerator.generateProxyClass(...); 이 예에서는 $Proxy0 클래스
2가 생성되고 새로 생성된 클래스는 전달된 첫 번째 매개변수인 classloder를 통해 jvm에 로드됩니다. $Proxy0 클래스 로드
3. 세 번째 매개변수를 사용하여 $Proxy0의 $Proxy0(InvocationHandler) 생성자를 호출하여 $Proxy0 개체를 생성하고, 인터페이스 매개변수를 사용하여 모든 해당 인터페이스의 메서드를 순회하고 메소드 객체 초기화 객체 여러 메소드 멤버 변수
4, $Proxy0 인스턴스를 클라이언트에 반환합니다.
지금은 괜찮아요. 클라이언트가 이를 어떻게 조정하는지 살펴보겠습니다. 그러면 명확해질 것입니다.
1. 클라이언트는 $Proxy0의 인스턴스 객체를 가져옵니다. $Proxy0은 BusinessProcessor를 상속하므로 BusinessProcessor로 변환하는 데 문제가 없습니다.
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);
2. bp.processBusiness();
실제로 호출되는 것은 $Proxy0.processBusiness()이고 $Proxy0.processBusiness입니다. ()의 구현은 InvocationHandler를 통해 호출 메소드를 호출하는 것입니다!

위는 Java 동적 프록시 적용에 대한 자세한 설명입니다. 자세한 내용은 PHP 중국어 웹사이트(www. php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.