jdk动态代理

上次给大家举了个例子 QQ 车的例子  QQ车装饰者模式加强QQ车的功能的方法 在不破坏原有对象的的基础上进行加强,

那么我们现在又想给QQ车 加强一些功能呢?  按照装饰者模式的思想 我们又得去写一个qqWrepper类增加功能,如果有

几十个上百个功能需要加强呢?我们就要写好几十个类 代码量太多。

     有没有一种方式 能让我们获取到一个被加强的对象 而且又不需要写qqwrepper类 。 有 ,就是今天要引入的动态代理。

不用写qqwrepper,直接返回一个被加强的对象。

 

jdk动态代理 必须要有接口

看看jdk代理如何在不需要写装饰类的前提下 直接返回一个被加强的对象。

 

在java的反射包下有一个proxy类

查阅api文档

      object obj= proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

    JDK 中提供了这个方法 帮你创建一个实例对象,要求你传入三个参数,不需要写类  直接返回一个加强对象 

    第一个传入对象参数 ClassLoader:类加载器  因为它要帮你直接返回一个已被增强的对象,必须有一个对应的类加载在内存中的,

                     这里本应该传入的是一个 加强过对象的类加载器,但是一般传入的被加强对象的类加载器。

              interfaces    传入的是增强对象的接口列表  保证被加强对象和加强对象的声明保持保持一致。

              InvocationHandler  执行处理类 接口  传参数的时候一定是一个对象。InvaocationHandler接口的实现类对象

    

  InvocationHandler接口中只有一个方法 invoke 方法

      

  invoke(Object proxy, Method method, Object[] args)

    proxy:指的是即将被返回的已经被加强过的对象。

    Method:指的是执行的方法。

    args: 方法执行的参数列表  

    上代码看看:

public class Demo {
    public static void main(String[] args) throws Exception {
        final QQ qq = new QQ();
        //使用动态代理 增强它
        Car zengqian = (Car) Proxy.newProxyInstance(qq.getClass().getClassLoader(),qq.getClass().getInterfaces(), new InvocationHandler() {
                    @Override                                            
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                             proxy 代表即将返回的代理对象 
                        String name = method.getName();

      
                        if("run".equals(name)){  

        加强你想增加的方法  其他方法不需要增强 就执行原来的方法 


                            long start = System.currentTimeMillis();  qq 车加速之前的时间

          
                            Object invoke = method.invoke(qq);  原有对象的引用


                            long end = System.currentTimeMillis(); qq车加速之后的时间


                            System.out.println(end-start);


                            return invoke;
                        }else{
                             method.invoke(qq,args);   调用deriver 方法需要参数 传入参数。
                             return 100;
                        }
                    }
                });
        
        
        //zengqian.run();
        //zengqian.stop();
        //zengqian.driver("小明"); 
        int oilTank = zengqian.oilTank();
        System.out.println(oilTank);
        
        
    }
}

  

 

posted @ 2018-05-24 21:48  ShouldStrong  阅读(114)  评论(0编辑  收藏  举报