自定义实现Java动态代理
阅读原文时间:2023年07月15日阅读:1

转自:https://www.cnblogs.com/rjzheng/p/8750265.html

一 借助JDK的API实现:

1.先创建一个接口,并实现它

public interface Person {
void eat();
}

public class PersonImpl implements Person {
@Override
public void eat() {
System.out.println("eat…………");
}
}

2.实现InvocationHandler:每一个动态代理类都要实现这个接口

public class PersonInvocationHandler implements InvocationHandler {

 //我们要代理的真实对象  
 private Object obj;

 public PersonInvocationHandler(Object obj) {  
     this.obj = obj;  
 }

 /\*\*  
  \* Object proxy:  
  \* 1. 可以使用反射获取代理对象的信息(也就是proxy.getClass().getName())。  
  \* 2. 可以将代理对象返回以进行连续调用,这就是proxy存在的目的,因为this并不是代理对象。  
  \*/  
 @Override  
 public Object invoke(Object proxy, Method method, Object\[\] args) throws Throwable {  
     System.out.println("before eat.......");  
     //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用  
     method.invoke(obj, args);  
     System.out.println("after eat.......");  
     return null;  
 }  

}

3.测试

public class JdkTest {
public static void main(String[] args) {
PersonInvocationHandler personInvocationHandler = new PersonInvocationHandler(new PersonImpl());

     Person personProxy = (Person) Proxy.newProxyInstance(PersonImpl.class.getClassLoader(),  
             PersonImpl.class.getInterfaces(), personInvocationHandler);

     personProxy.eat();  
 }  

}

返回结果:

二 自定义动态代理

1.自定义InvocationHandler

public interface MyInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

2.实现自定义的MyInvocationHandler

public class PersonInvocationHandler implements MyInvocationHandler {

 //我们要代理的真实对象  
 private Object obj;

 public PersonInvocationHandler(Object obj) {  
     this.obj = obj;  
 }

 /\*\*  
  \* Object proxy:  
  \* 1. 可以使用反射获取代理对象的信息(也就是proxy.getClass().getName())。  
  \* 2. 可以将代理对象返回以进行连续调用,这就是proxy存在的目的,因为this并不是代理对象。  
  \*/  
 @Override  
 public Object invoke(Object proxy, Method method, Object\[\] args) throws Throwable {  
     System.out.println("before eat.......");  
     //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用  
     method.invoke(obj, args);  
     System.out.println("after eat.......");  
     return null;  
 }  

}

3.自定义ClassLoader

public class MyClassLoader extends ClassLoader{

 private File classPathFile;

 public MyClassLoader() {  
     String classPath = MyClassLoader.class.getResource("").getPath();  
     this.classPathFile = new File(classPath);  
 }

 public Class<?> findClass(String name) {  
     String className = MyClassLoader.class.getPackage().getName() + "." + name;  
     if (classPathFile != null){  
         File file = new File(classPathFile, name + ".class");  
         FileInputStream inputStream = null;  
         ByteArrayOutputStream outputStream = null;  
         try {  
             inputStream = new FileInputStream(file);  
             outputStream = new ByteArrayOutputStream();  
             byte\[\] buf = new byte\[1024\];  
             int len ;  
             while ((len = inputStream.read(buf)) != -1){  
                 outputStream.write(buf, 0, len);  
             }  
             return defineClass(className, outputStream.toByteArray(), 0, outputStream.size());  
         }catch (Exception e){  
             e.printStackTrace();  
         }finally {  
             if(null!=inputStream){  
                 try {  
                     inputStream.close();  
                 } catch (IOException e) {  
                     // TODO Auto-generated catch block  
                     e.printStackTrace();  
                 }  
             }  
             if(null!=outputStream){  
                 try {  
                     outputStream.close();  
                 } catch (IOException e) {  
                     // TODO Auto-generated catch block  
                     e.printStackTrace();  
                 }  
             }  
         }  
     }  
     return null;  
 }  

}

4.自定义Proxy代理类

  主要流程:1.将源码输入到Java文件

       2.将Java文件编译成class文件

       3.将class加载进jvm

       4.返回代理类对象

public class MyProxy {
public static final String ln = "\r\n";

public static Object newProxyInstance(MyClassLoader classLoader,  
                                      Class<?>\[\] interfaces, MyInvocationHandler handler) {  
    try {  
        //1.java源码  
        String src = generateSrc(interfaces);  
        //2.将源码输出到Java文件中  
        String filePath = MyProxy.class.getResource("").getPath();  
        System.out.println(filePath);  
        File file = new File(filePath + "$Proxy0.java");  
        FileWriter fw = new FileWriter(file);  
        fw.write(src);  
        fw.flush();  
        fw.close();  
        //3.将Java文件编译成class文件  
        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();  
        StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null, null, null);  
        Iterable iterable = manager.getJavaFileObjects(file);  
        JavaCompiler.CompilationTask task = javaCompiler.getTask(null, manager, null, null,null, iterable);  
        task.call();  
        manager.close();  
        //4.将class加载进jvm  
        Class proxyClass = classLoader.findClass("$Proxy0");  
        file.delete();  
        //5.返回代理类对象  
        Constructor constructor = proxyClass.getConstructor(MyInvocationHandler.class);  
        return constructor.newInstance(handler);  
    }catch (Exception e){  
        e.printStackTrace();  
    }  
    return null;  
}

//Java源码  
private static String generateSrc(Class<?>\[\] interfaces) {  
    // TODO Auto-generated method stub  
    StringBuffer sb = new StringBuffer();  
    sb.append("package xin.hangzhi.jdk.proxy.demo.custom;" + ln);  
    sb.append("import java.lang.reflect.Method;" + ln);  
    sb.append("public class $Proxy0 implements " + interfaces\[0\].getName() + "{" + ln);  
    sb.append("private MyInvocationHandler h;"+ln);  
    sb.append("public $Proxy0(MyInvocationHandler h) { " + ln);  
    sb.append("this.h = h;"+ln);  
    sb.append("}" + ln);  
    for (Method m : interfaces\[0\].getMethods()) {  
        sb.append("public " + m.getReturnType().getName() + " "  
                + m.getName() + "() {" + ln);  
        sb.append("try{" + ln);  
        sb.append("Method m = " + interfaces\[0\].getName()  
                + ".class.getMethod(\\"" + m.getName()  
                + "\\",new Class\[\]{});" + ln);  
        sb.append("this.h.invoke(this,m,null);" + ln);  
        sb.append("}catch(Throwable e){" + ln);  
        sb.append("e.printStackTrace();" + ln);  
        sb.append("}"+ln);  
        sb.append("}"+ln);  
    }  
    sb.append("}" + ln);  
    return sb.toString();  
}  

}

5.测试结果