간단 한 JDK 버 전 동적 에이전트

10687 단어 JDK동적 에이전트
본 고의 실례 는 여러분 에 게 수 동 으로 실 현 된 간단 한 JDK 판 동적 에이 전 트 를 공유 하 였 습 니 다.여러분 께 참고 하 시기 바 랍 니 다.구체 적 인 내용 은 다음 과 같 습 니 다.
실현 절차
1.대상 클래스 의 인터페이스 형식 에 따라 프 록 시 클래스 의 자바 파일 을 생 성 합 니 다.
2.프 록 시 클래스 자바 파일 을.class 바이트 파일 로 컴 파일 합 니 다.
3.컴 파일 된 바이트 파일 을 jvm 에 불 러 옵 니 다.
4.프 록 시 대상 을 생 성하 고 되 돌려 줍 니 다.
코드 구현
1.프 록 시 클래스

public class CLProxy  {
  private static final String ENTER= "\r
"; private static final String PAKAGE=CLProxy.class.getPackage().toString()+";"; private static final String CLASS_NAME="$Proxy"; private static final AtomicInteger NUMBER= new AtomicInteger(0); public static Object newProxyInstance(CLClassLoader classLoader, Class<?>[] interfaces,CLInvocationHandler h) throws Exception{ String className =CLASS_NAME+NUMBER.getAndIncrement(); // java String javaString = createJavaString(interfaces, className); String parentPath = CLProxy.class.getResource("").getPath(); File file =new File(parentPath,className+".java" ); FileWriter writer = new FileWriter(file); writer.write(javaString); writer.flush(); writer.close(); //System.out.println(file); // JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = systemJavaCompiler.getStandardFileManager(null, null, null); Iterable<? extends JavaFileObject> javaFileObjects = standardFileManager.getJavaFileObjects(file); JavaCompiler.CompilationTask task = systemJavaCompiler.getTask(null, standardFileManager, null, null, null, javaFileObjects); task.call(); standardFileManager.close(); // Class<?> aClass = classLoader.findClass(className); Constructor<?> constructor = aClass.getConstructor(CLInvocationHandler.class); Object instance = constructor.newInstance(h); //file.delete(); return instance; } /** * java * @param interfaces * @return */ private static String createJavaString(Class<?>[] interfaces , String className ){ StringBuffer buffer = new StringBuffer(); buffer.append(PAKAGE+ENTER); buffer.append("import java.lang.reflect.Method;"+ ENTER); StringBuffer interfaceString= new StringBuffer(); int length= interfaces.length; for (int i = 0; i<length ; ++i){ interfaceString.append(interfaces[i].getName()); if (i!=length-1){ interfaceString.append(","); } } buffer.append("public final class "); buffer.append(className); buffer.append(" implements "); buffer.append(interfaceString); buffer.append(" {"+ENTER); buffer.append("private CLInvocationHandler handler;"+ENTER); buffer.append("public "+className+"(CLInvocationHandler handler) {"+ENTER); buffer.append(" this.handler= handler;"+ENTER); buffer.append("}"+ENTER); for (int i =0 ;i<length;++i){ Class<?> clazz= interfaces[i]; Method[] methods = clazz.getMethods(); for (Method method : methods){ String returnTypeString = method.getReturnType().getName(); Class<?>[] parameterTypes = method.getParameterTypes(); StringBuffer paramTypeString = new StringBuffer(); StringBuffer methodParamString = new StringBuffer(); StringBuffer invokeParamString = new StringBuffer(); paramTypeString.append("new Class[]{"); int paramLength= parameterTypes.length; for (int j =0 ; j<paramLength ;++j){ Class<?> paramClazz= parameterTypes[j]; paramTypeString.append(paramClazz.getName()+".class"); String paramFieldName = "var"+j; methodParamString.append(paramClazz.getName() +" "+paramFieldName); invokeParamString.append(paramFieldName); if (j!= paramLength-1){ paramTypeString.append(","); methodParamString.append(","); invokeParamString.append(","); } } paramTypeString.append("}"); int modifiers = method.getModifiers(); if (Modifier.isPublic(modifiers)){ buffer.append("public"); }else if (Modifier.isPrivate(modifiers)){ buffer.append("private"); }else if (Modifier.isProtected(modifiers)){ buffer.append("protected"); } buffer.append(" final "+returnTypeString+" "+ method.getName()+"("+methodParamString+"){"+ ENTER); buffer.append("try{"+ENTER); buffer.append("Method method = "+clazz.getName()+".class.getMethod(\""+method.getName()+"\","+paramTypeString+" );"+ENTER); if (!"void".equals(returnTypeString)){ buffer.append("return ("+returnTypeString+")"); } if (invokeParamString.toString().length()==0){ invokeParamString.append("null"); }else{ invokeParamString = new StringBuffer("new Object[]{"+invokeParamString.toString()+"}"); } buffer.append("this.handler.invoke(this,method,"+invokeParamString+");"+ENTER); buffer.append("}catch(Throwable e){"+ENTER); buffer.append("e.printStackTrace();"+ENTER); buffer.append("}"+ENTER); if (!"void".equals(returnTypeString)){ buffer.append("return null;"+ENTER); } buffer.append("}"+ENTER); } } buffer.append("}"); return buffer.toString(); } public static void main(String[] args) throws Exception { Person person = (Person)CLProxy.newProxyInstance(new CLClassLoader(), XiaoMing.class.getInterfaces(), new CLInvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before"); Object result= method.invoke(new XiaoMing(), args); System.out.println("after"); return result; } }); String laoxu = person.call("laoxu"); System.out.println(laoxu); /* person.eat(); Class<?>[] interfaces = person.getClass().getInterfaces(); for (Class<?> in:interfaces){ System.out.println(in.getName()); } */ Person person2= (Person)CLProxy.newProxyInstance(new CLClassLoader(), XiaoMing.class.getInterfaces(), new CLInvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before"); Object result= method.invoke(new XiaoMing(), args); System.out.println("after"); return result; } }); System.out.println(person2.getClass()); } }
2.InvocationHandler 인터페이스

public interface CLInvocationHandler {
 
  public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable;
 
}
3.ClassLoader 클래스 로 더

public class CLClassLoader extends ClassLoader {
 
  private File classPathFile;
 
  public CLClassLoader(){
 
    String classPath = CLClassLoader.class.getResource("").getPath();
 
    this.classPathFile= new File(classPath);
  }
 
 
  @Override
  protected Class<?> findClass(String name) throws ClassNotFoundException {
 
 
    String className = CLClassLoader.class.getPackage().getName()+"."+name;
 
 
 
    if (classPathFile!= null ){
 
 
      File classFile = new File(classPathFile, name.replace("\\.", "/") + ".class");
 
 
      if (classFile.exists()){
 
 
        FileInputStream inputStream =null;
 
        ByteArrayOutputStream outputStream = null;
        try{
          inputStream=new FileInputStream(classFile);
 
          outputStream= new ByteArrayOutputStream();
 
          byte[] bytes = new byte[1024];
          int len;
          while ((len=inputStream.read(bytes))!=-1){
            outputStream.write(bytes,0,len);
          }
          return defineClass(className,outputStream.toByteArray(),0,outputStream.size());
        }catch (Exception e){
          e.printStackTrace();
        }finally {
          if (inputStream!= null){
            try {
              inputStream.close();
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
          if (outputStream!=null){
            try {
              outputStream.close();
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
        }
 
 
 
      }
 
 
 
 
    }
    return super.findClass(name);
  }
}
4.테스트 에 사용 되 는 인터페이스 와 대상 클래스

//       
public interface Person {
 
  void eat();
 
  String call(String name);
}
 
 
//       
public class XiaoMing implements Person {
  @Override
  public void eat() {
    System.out.println("   ");
  }
 
  //@Override
  public String call(String name) {
    return name;
  }
}
테스트 방법 은 CLProxy main 방법 에 있 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기