首页 > 世达工具代理 > JDK动态代理手写实现

JDK动态代理手写实现

MyProxy.java:模拟Proxy

package com.proxy;

import java.io.File;

import java.io.FileWriter;

import java.io.IOException;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import javax.tools.JavaCompiler;

import javax.tools.JavaCompiler.CompilationTask;

import javax.tools.StandardJavaFileManager;

import javax.tools.ToolProvider;

/**

  • 模拟实现jdk动态代理 (基于接口实现)
  • @author Administrator
  • */
  • public class MyProxy {
  • static String rt = "\r\t";
  • static String packageDir="com.proxy";

/**

  • 此方法为产生代理对象的方法
  • @param loader
  • 类加载器
  • @param interfaces
  • 代理接口类(原jdk里面是数组 因为一个类可以实现多个接口)
  • @param h
  • 代理对象
  • @return
  • */
  • public static Object newProxyInstance(ClassLoader loader, Class interfaces,
  • MyInvocationHandler h) {
  • String javaDir = "src/"+packageDir.replace(".", "/");
  • String javaName = "$Proxy0";
  • String fileName = javaDir + "/" + javaName + ".java";
  • // 1产生动态代理类源文件 get$proxy0.java
  • String javaFileStr = get$Proxy0(interfaces);
  • // 2生成源文件
  • createJavaFile(javaFileStr, fileName);
  • // 3编译源文件
  • compilerJava(fileName);

// 4加载类 生成Class对象

Class cls=findClass(javaDir,javaName);

// 5构建代理对象

Object obj=newInstance(cls,h);

//6 删除文件

deleteFile(fileName);

return obj;

}

private static void deleteFile(String fileName) {

// TODO Auto-generated method stub

File file=new File(fileName);

file.delete();

}

private static Object newInstance(Class cls, MyInvocationHandler h) {

// TODO Auto-generated method stub

Constructor cons;

Object obj=null;

try {

cons = cls.getConstructor(MyInvocationHandler.class);

obj=cons.newInstance(h);

} catch (NoSuchMethodException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (SecurityException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InstantiationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalArgumentException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InvocationTargetException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return obj;

}

private static Class findClass(String javaDir, String javaName) {

// TODO Auto-generated method stub

MyClassLoader myloader = new MyClassLoader(javaDir);

Class cls = null;

try {

cls = myloader.findClass(javaName);

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return cls;

}

// 通过代码编译java

private static void compilerJava(String fileName) {

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();// 获取编译器

StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null,

null, null);

Iterable units = fileMgr.getJavaFileObjects(fileName);

CompilationTask task = compiler.getTask(null, fileMgr, null, null,

null, units);

task.call();

try {

fileMgr.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

// 生成java文件

private static void createJavaFile(String javaFileStr, String fileName) {

File file = new File(fileName);// File类

FileWriter fw = null;

try {

fw = new FileWriter(file);

fw.write(javaFileStr);

fw.flush();

} catch (IOException e) {

e.printStackTrace();

} finally {

if (fw != null) {

try {

fw.close();

} catch (IOException e) {

}

}

}

}

/**

  • 拼接代理类字符串
  • @return
  • */
  • private static String get$Proxy0(Class interfaces) {
  • StringBuffer javaFile = new StringBuffer("package com.proxy;" + rt);// 定义包
  • javaFile.append("import java.lang.reflect.Method;" + rt);// 导入包
  • javaFile.append("public class $Proxy0 implements "
  • interfaces.getName() + "{" + rt);// 定义类实现接口
  • javaFile.append("MyInvocationHandler h;" + rt);// 定义代理对象
  • javaFile.append("public $Proxy0(MyInvocationHandler h){" + rt);
  • javaFile.append("this.h=h;" + rt);
  • javaFile.append("}" + rt);
  • javaFile.append(getMethodStr(interfaces.getMethods(), interfaces) + rt);// 拼接方法
  • javaFile.append("}" + rt);
  • return javaFile.toString();
  • }

/**

  • 方法的拼接
  • @return
  • */
  • private static String getMethodStr(Method[] methods, Class infs) {
  • // TODO Auto-generated method stub
  • StringBuffer methodStr = new StringBuffer();// 方法字符串
  • for (Method method : methods) {// 遍历方法对象
  • methodStr.append("public void " + method.getName() + "() throws Throwable {" + rt);
  • methodStr.append("Method md=" + infs.getName()
  • ".class.getMethod(\"" + method.getName()
  • "\",new Class[]{});" + rt);
  • methodStr.append("this.h.invoke(this,md,null);" + rt);
  • methodStr.append("}" + rt);
  • }
  • return methodStr.toString();
  • }
  • }
  • MyInvocationHandler.java 模拟InvocationHandler
  • package com.proxy;

import java.lang.reflect.Method;

/**

  • 定义代理拦截器
  • @author Administrator
  • */
  • public interface MyInvocationHandler {
  • /**
  • 代理接口实现方法
  • @param proxy 代理对象
  • @param method 代理方法
  • @param args 参数
  • @return 返回源目标方法结果
  • @throws Throwable 异常声明
  • */
  • public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
  • }
  • MyClassLoader.java 实现自定义类加载器
  • package com.proxy;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

/**

  • 自定义类加载器
  • @author Administrator
  • */
  • public class MyClassLoader extends ClassLoader {
  • private File dir;
  • public MyClassLoader(String filePath){
  • dir=new File(filePath);
  • }
  • @Override
  • /**
  • 找类
  • */
  • protected Class<?> findClass(String name) throws ClassNotFoundException {
  • // TODO Auto-generated method stub
  • if(dir!=null){
  • File classFile=new File(dir,name+".class");
  • if(classFile.exists()){
  • FileInputStream fis=null;
  • try {
  • fis=new FileInputStream(classFile);
  • //创建字节数组流对象
  • ByteArrayOutputStream bais=new ByteArrayOutputStream();
  • //创建字节数组
  • byte[] buffer=new byte[1024];
  • int len=0;
  • while((len=fis.read(buffer))>0){//循环读取
  • bais.write(buffer, 0, len);
  • }
  • //bais.size() 字节流大小
  • Class cls=defineClass(MyProxy.packageDir+"."+name, bais.toByteArray(), 0, bais.size());
  • return cls;
  • } catch (FileNotFoundException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • } catch (IOException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • }finally{
  • if(fis!=null)try {fis.close();} catch (IOException e) {e.printStackTrace();}
  • }
  • }
  • }
  • return super.findClass(name);
  • }
  • }
  • Person.java代理接口类
  • package com.proxy;

/**

  • jdk动态代理实现 基于接口实现
  • 人类接口
  • @author Administrator
  • */
  • public interface Person {

/**

  • 吃的方法
  • */
  • public void eat() throws Throwable;
  • }
  • PersonInvocationHandler.java 代理目标对象类
  • package com.proxy;

import java.lang.reflect.Method;

/**

  • jdk动态代理对象
  • @author Administrator
  • */
  • public class PersonInvocationHandler implements MyInvocationHandler {
  • //代理目标对象
  • private Object target;
  • //构造方法 传入代理目标对象
  • public PersonInvocationHandler(Object target){
  • this.target=target;
  • }
  • @Override
  • //proxy 生成的代理对象
  • public Object invoke(Object proxy, Method method, Object[] args)
  • throws Throwable {
  • before();
  • method.invoke(target, args);
  • after();
  • return null;
  • }
  • public void before(){
  • System.out.println("吃饭前洗手");
  • }
  • public void after(){
  • System.out.println("吃饭后漱口");
  • }
  • }
  • ZhanSan.java 目标对象类
  • package com.proxy;

public class ZhanSan implements Person {

@Override

public void eat() {

System.out.println("吃饭的方法");

}

}

Test.java测试类

package com.proxy;

public class Test {

/**

  • @param args
  • @throws Throwable
  • */
  • public static void main(String[] args) throws Throwable {
  • // TODO Auto-generated method stub
  • Person person=new ZhanSan();
  • MyInvocationHandler handler=new PersonInvocationHandler(person);
  • person=(Person)MyProxy.newProxyInstance(Test.class.getClassLoader(), Person.class, handler);
  • person.eat();
  • }

}

JDK动态代理手写实现

,可以参考MRO工业品采购的资料,