`
m635674608
  • 浏览: 5028763 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

模拟JDK动态代理

    博客分类:
  • java
 
阅读更多
接口Moveable:

public interface Moveable {
 public void move();
 public void stop();
}
接口的实现类Tank:
public class Tank implements Moveable{
        public void move() {
       System.out.println("tank is moving...");
       try {
           Thread.sleep(new Random().nextInt(10000));
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
    }
    @Override
    public void stop() {
       System.out.println("tank stoped...");
    }

}

模拟的InvocationHandler:
public interface InvocationHandler {
    public void invoke(Object object,Method method);

}

InvocationHandler的实现,也即应用类LogHandler:
public class LogHandler implements InvocationHandler{
    private Object target;//被代理对象
    public LogHandler(Object object) {
       super();
       this.target = object;
    }
    @Override
    public void invoke(Object object,Method method) {
       //先调用自己的逻辑,然后调用被代理对象的方法,最后再调用自己的逻辑
       System.out.println("log begin...");
       try {
           method.invoke(target);
       } catch (Exception e) {
           e.printStackTrace();
       }
       System.out.println("log end...");
    }

}

本文中最重要的代理类Proxy:
public class Proxy {
    public static Object newProxyInstance(Class interClass,InvocationHandler handler) throws Exception{
       String srcString="";//源代码字符串
       String rt = "\r\n";//回车换行符
       String methodString = "";//方法字符串
       Method[] methods = interClass.getMethods();//找出接口interClass中的所有方法
       for(Method method:methods){
           //将接口中的所有方法拼接为方法字符串
           methodString += 
                     "   public void " + method.getName() +"(){" + rt +//方法头部
                     "   try{" + rt +
                     "      Method md = " +interClass.getName() +".class.getMethod(\"" + method.getName() +"\");" + rt +//获得接口中的一个方法
                     "      handler.invoke(this,md);" + rt +//用处理器handler进行处理
                     "   }catch(Exception e){" + rt +
                     "      e.printStackTrace();" + rt +
                     "   }" + rt +
                     "   }" + rt ;
       }
       srcString = "package com.hibernate.proxy;" + rt +
                  "import java.lang.reflect.Method;" + rt +
                  "public class $Proxy1 implements "+ interClass.getName() + "{" + rt +//此处应注意:@Proxy1一定要记得实现传过来的接口
                  "   private InvocationHandler handler;" + rt +//代理中应该保存一个处理器handler,并在构造函数中进行传递
                  "   public $Proxy1(InvocationHandler handler){" +rt +
                  "      this.handler = handler;" + rt +
                  "   }" + rt +
                  methodString + rt +
                  "}";
       String fileName = System.getProperty("user.dir")+"/src/com/hibernate/proxy/$Proxy1.java";//这个是文件的名称
       File file = new File(fileName);//新建文件
       if(!file.exists()){
           file.createNewFile();
       }
       FileWriter writer = new FileWriter(file);
       writer.write(srcString);//将源代码写到文件中
       writer.flush();
       writer.close();
       //以下的部分是对刚才新建的源代码文件尽心编译
       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
       StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
       Iterable units = manager.getJavaFileObjects(fileName);
       CompilationTask task = compiler.getTask(null, manager, null, null, null, units);
       task.call();
       manager.close();
       //将编译后的文件加载到内存
       URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir"+"/src"))};
       URLClassLoader classLoader = new URLClassLoader(urls);
       Class class1 = classLoader.loadClass("com.hibernate.proxy.$Proxy1");
       //生成新的对象
       //获得代理对象$proxy1的构造方法,并将参数的类型传给它
       Constructor constructor = class1.getConstructor(InvocationHandler.class);
       //构造一个新的代理对象,参数为传进来的handler
       Object object = (Object)constructor.newInstance(handler);
       //返回新生成的代理对象
       return object;
    }

}

测试类:
public class ProxyTest {
    public static void main(String[] args) {
       Tank tank = new Tank();
       InvocationHandler handler = new LogHandler(tank);
       try {
           Moveable moveable = (Moveable)Proxy.newProxyInstance(Moveable.class, handler);//生成一个和被代理对象具有相同接口的代理对象
           moveable.move();
           moveable.stop();
       } catch (Exception e) {
           e.printStackTrace();
       }
    }

}

编译生成的$Proxy1类:
package com.hibernate.proxy;
import java.lang.reflect.Method;
public class $Proxy1 implements com.hibernate.proxy.Moveable{
    private InvocationHandler handler;
    public $Proxy1(InvocationHandler handler){
       this.handler = handler;
    }
    public void stop(){
    try{
       Method md = com.hibernate.proxy.Moveable.class.getMethod("stop");
       handler.invoke(this,md);
    }catch(Exception e){
       e.printStackTrace();
    }
    }
    public void move(){
    try{
       Method md = com.hibernate.proxy.Moveable.class.getMethod("move");
       handler.invoke(this,md);
    }catch(Exception e){
       e.printStackTrace();
    }
    }
 

}

 

分享到:
评论

相关推荐

    模拟JDK动态代理内部实现

    在本文中,我们将深入探讨如何模拟JDK的动态代理内部实现。 首先,我们需要了解JDK动态代理的基础知识。Java中的动态代理通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。`Proxy...

    JDK动态代理proxy

    - 远程调用:在RMI(Remote Method Invocation)中,可以使用动态代理模拟远程对象的行为。 - 插件系统:允许插件在运行时动态扩展系统功能,而无需修改原有代码。 总结,JDK动态代理是一种强大的工具,它允许我们...

    静态代理动态代理测试,模拟jdk实现动态代理

    在实际应用中,动态代理常用于AOP(面向切面编程)场景,例如Spring框架中的AOP代理就是基于JDK动态代理或者CGLIB来实现的,可以在方法调用前、后或异常时插入自定义的行为。 通过上述的静态代理和动态代理的讲解,...

    模拟spring aop【一】基于jdk动态代理实现的aop

    - Spring AOP提供了`DefaultAdvisorAutoProxyCreator`,它可以自动为匹配的Bean创建JDK代理。 - 切面(Aspect)是Spring AOP的核心,它封装了通知(Advice),通知定义了切面的逻辑。例如,我们可以创建一个`...

    jdk动态代理使用[文].pdf

    在Java编程中,JDK动态代理是一种强大的工具,它允许我们在运行时创建代理类来拦截对目标对象的调用,从而实现额外的功能,比如日志记录、性能监控、事务管理等,而无需修改原始代码。这里我们将深入探讨JDK动态代理...

    jdk动态代理

    在JDK中,动态代理是一种强大的功能,它允许我们在运行时创建代理对象,这些代理对象可以作为其他对象的代理,执行额外的操作或者扩展目标对象的功能。动态代理在很多场景下都非常有用,例如AOP(面向切面编程)、...

    JDK动态代理

    在Java开发中,JDK动态代理是一个非常重要的特性,它允许我们在运行时创建对现有接口的代理实现。这种代理对象可以拦截方法调用,并在调用前后执行自定义的逻辑,而无需修改原始代码。本篇文章将深入探讨JDK动态代理...

    JDK内置动态代理例子

    在Java开发中,JDK内置的动态代理机制是一种强大的工具,它允许我们在运行时创建具有额外功能的对象。这个“JDK内置动态代理例子”旨在演示如何利用Java的反射API和`java.lang.reflect.Proxy`类来实现类似拦截器的...

    jdk动态代理模拟AOP拦截器

    NULL 博文链接:https://xxjkcyt.iteye.com/blog/1413467

    个人用java动态代理模拟实现spring aop

    首先,我们需要了解Java中的两种动态代理机制:JDK动态代理和CGLIB动态代理。JDK动态代理基于接口实现,适用于目标对象实现了接口的情况;而CGLIB则是通过字节码技术,可以在无接口的情况下生成目标类的子类,实现对...

    SpringAOP的实现机制(底层原理)、应用场景等详解,模拟过程的实例

    本资源将深入探讨Spring框架中使用的两种关键的动态代理方式:JDK动态代理和CGLib动态代理。这两种代理方式在Spring AOP中起到关键作用,用于实现横切关注点的切面编程。通过学习它们的原理和实际应用,您将能够更好...

    使用ImportBeanDefinitionRegistrar、JDK代理、FactoryBean模拟mybatis原理.zip

    接下来,JDK代理是Java提供的一种动态代理机制,它允许我们在运行时创建一个代理类,该类可以对目标对象的方法调用进行拦截和增强。在MyBatis中,SqlSession的每个方法调用都会被代理,使得我们可以插入SQL执行前后...

    动态代理原理实例Demo

    - 动态代理还可用于模拟远程调用,比如RMI(远程方法调用)中的代理对象,以及单元测试中模拟依赖对象。 综上所述,Java动态代理提供了一种灵活的方式,可以在不修改原对象代码的情况下,扩展或修改其行为。通过...

    简单模拟spring cglib代理

    Spring支持两种代理机制:基于接口的JDK动态代理和基于类的CGLIB代理。 CGLIB(Code Generation Library)是一个强大的高性能代码生成库,其底层是通过使用操作Java字节码的开源字节码操作框架(比如ASM)来实现的...

    java的动态代理

    Java提供了两种动态代理机制:基于接口的JDK动态代理和基于类的CGLIB动态代理。本案例主要关注基于接口的JDK动态代理。 #### 三、JDK动态代理的关键步骤 1. **定义接口**: - 首先定义一个接口`Speak`,它规定了...

    java dtdl 动态代理

    CGlib通过生成字节码动态创建子类实现,适用于不满足JDK代理的情况。 总结,Java动态代理是Java设计模式中的一种重要工具,它为开发者提供了在运行时扩展或增强已有对象功能的能力,是实现AOP和提高代码灵活性的...

    cglib动态代理介绍

    在Java中,JDK自带的动态代理机制是基于接口的,如果被代理的类没有实现任何接口,那么就无法使用JDK的动态代理。而CGlib则弥补了这一不足,它通过字节码技术生成目标类的子类,然后在子类中拦截父类方法的调用,...

Global site tag (gtag.js) - Google Analytics