美文网首页
Java的反射机制 (二)动态代理(仅供复习查阅)

Java的反射机制 (二)动态代理(仅供复习查阅)

作者: lhsjohn | 来源:发表于2018-12-13 22:02 被阅读0次

    代理类在程序运行时创建的代理方式被成为动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。

    Object invoke(Object proxy,
                  方法 method,
                  Object[] args)
           throws Throwable处理代理实例上的方法调用并返回结果。 当在与之关联的代理实例上调用方法时,将在调用处理程序中调用此方法。 
    参数 
    proxy - 调用该方法的代理实例 
    method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。 
    args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。 
    

    1.代理是基本的设计模式之一,下面展示一个用来展示代理结构的小示例

    package com.lhsjohn.typeinfo.prac;
    /**
     * 这是一个展示代理结构的简单示例
     * @author lihuashuo
     *
     */
    
    interface Interface{
        void doSomething();
        void somethingElse(String arg);
    }
    
    class RealObject implements Interface{
    
        @Override
        public void doSomething() {
            System.out.println("do something.....");
            
        }
    
        @Override
        public void somethingElse(String arg) {
            System.out.println("somethingElse"+ arg);
            
        }
        
    }
    
    class SimpleProxy implements Interface{
       
        private Interface proxied;
        
        
        
        public SimpleProxy(Interface proxied) {
            this.proxied = proxied;
        }
    
        @Override
        public void doSomething() {
         System.out.println("simpleProxy doSomething");
         proxied.doSomething();
            
        }
    
        @Override
        public void somethingElse(String arg) {
            System.out.println("simpleProxy do Something Else"+arg);
            proxied.somethingElse(arg);
        }
        
    }
    
    
    public class SimpleProxyDemo {
       
        public static void consumer(Interface iface) {
            iface.doSomething();
            iface.somethingElse("hahahhh");
        }
        
        public static void main(String[] args) {
            consumer(new RealObject());
            consumer(new SimpleProxy(new RealObject()));
        }
    }
    
    

    运行结果

    do something.....
    somethingElsehahahhh
    simpleProxy doSomething
    do something.....
    simpleProxy do Something Elsehahahhh
    somethingElsehahahhh
    
    

    2.下面是动态代理的一个简单示例,采用动态代理的方法可以动态地创建代理并动态地处理对代理方法的调用

    package com.lhsjohn.typeinfo.prac;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    class DynamicProxyHandler implements InvocationHandler {
    
        private Object proxied;
    
        public DynamicProxyHandler(Object proxied) {
            this.proxied = proxied;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("*****proxy: " + proxy.getClass() + ", method: " + method + ", args:" + args);
            if (args != null) {
                for (Object arg : args) {
                    System.out.println("  " + arg);
                }
            }
    
            return method.invoke(proxied, args);
        }
    
    }
    
    public class SimpleDynamicProxy {
        
        public static void consumer(Interface iface) {
            iface.doSomething();
            iface.somethingElse("aaaaaaa ");
        }
        
        
        public static void main(String[] args) {
         
            RealObject real = new RealObject();
            consumer(real);
            
            Interface proxy = (Interface)Proxy.newProxyInstance(Interface.class.getClassLoader(), 
                    new Class[] {Interface.class}, new DynamicProxyHandler(real));
            consumer(proxy);
         
       }
     
     
     
    }
    

    运行结果

    do something.....
    somethingElseaaaaaaa 
    *****proxy: class com.lhsjohn.typeinfo.prac.$Proxy0, method: public abstract void com.lhsjohn.typeinfo.prac.Interface.doSomething(), args:null
    do something.....
    *****proxy: class com.lhsjohn.typeinfo.prac.$Proxy0, method: public abstract void com.lhsjohn.typeinfo.prac.Interface.somethingElse(java.lang.String), args:[Ljava.lang.Object;@28d93b30
      aaaaaaa 
    somethingElseaaaaaaa 
    

    3 过滤某些方法的调用

    package com.lhsjohn.typeinfo.prac;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    class MethodSelector implements InvocationHandler{
        private Object proxied;
        
        public MethodSelector(Object proxied) {
            this.proxied = proxied;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if(method.getName().equals("interesting")) {
                System.out.println("Proxy detected the interesting method");
            }
            
            return method.invoke(proxied, args);
        }
        
    }
     
    interface SomeMethods{
        void boring1();
        void boring2();
        void interesting(String arg);
        void boring3();
    }
    
    class Implementation implements SomeMethods{
    
        @Override
        public void boring1() {
            System.out.println("boring1");
            
        }
    
        @Override
        public void boring2() {
            System.out.println("boring2");
            
        }
    
        @Override
        public void interesting(String arg) {
            System.out.println("interesting "+ arg);
            
        }
    
        @Override
        public void boring3() {
            System.out.println("boring3");
            
        }
        
    }
    
    
    public class SelectingMethods {
       
        public static void main(String[] args) {
            SomeMethods proxy = (SomeMethods) Proxy.newProxyInstance(SomeMethods.class.getClassLoader(),
                    new Class[] {SomeMethods.class}, new MethodSelector(new Implementation()));
            
            proxy.boring1();
            proxy.boring2();
            proxy.interesting("sdfsdfs");
            proxy.boring3();
            
        }
    }
    
    

    运行结果:

    boring1
    boring2
    Proxy detected the interesting method
    interesting sdfsdfs
    boring3
    

    4.修改SimpleProxyDemo.java,使其可以度量方法调用的次数。

    package com.lhsjohn.typeinfo.prac;
    
    import java.util.Date;
    
    interface Interface{
        void doSomething();
        void somethingElse(String arg);
    }
    
    class RealObject implements Interface{
    
        @Override
        public void doSomething() {
            System.out.println("doSomething");
            
        }
    
        @Override
        public void somethingElse(String arg) {
           System.out.println("somethingElse "+arg);        
        }
        
    }
    
    class SimpleProxy implements Interface{
    
        private Interface proxied;
        private static int  doCount = 0;
        private static int sEcount = 0;
        public SimpleProxy(Interface proxied) {
            this.proxied = proxied;
        }
        
        
        @Override
        public void doSomething() {
            long timeIn = new Date().getTime();
            System.out.println("Time called doSomething() " + doCount+" : "+timeIn+" msecs");
            System.out.println("on " + new Date());
            doCount++;
            proxied.doSomething();
            System.out.println("Call-return time = "+(new Date().getTime()-timeIn)+ "msecs");
        }
    
        @Override
        public void somethingElse(String arg) {
            long timeIn = new Date().getTime();
            System.out.println("Time called somethingElse() " + doCount+" : "+timeIn+" msecs");
            System.out.println("on " + new Date());
            doCount++;
            proxied.somethingElse(arg);
            System.out.println("Call-return time = "+(new Date().getTime()-timeIn)+ "msecs");
            
        }
        
    }
    
    
    public class SimpleProxyDemo21 {
        public static void consumer(Interface iface) {
            iface.doSomething();
            iface.somethingElse("bonobo");
        }
        public static void main(String[] args) {
            consumer(new RealObject());
            System.out.println();
            consumer(new SimpleProxy(new RealObject()));
            System.out.println();
            consumer(new SimpleProxy(new RealObject()));
            System.out.println();
            consumer(new SimpleProxy(new RealObject()));                    
        }
    }
    

    运行结果:

    doSomething
    somethingElse bonobo
    
    Time called doSomething() 0 : 1536732268520 msecs
    on Wed Sep 12 14:04:28 CST 2018
    doSomething
    Call-return time = 17msecs
    Time called somethingElse() 1 : 1536732268537 msecs
    on Wed Sep 12 14:04:28 CST 2018
    somethingElse bonobo
    Call-return time = 0msecs
    
    Time called doSomething() 2 : 1536732268537 msecs
    on Wed Sep 12 14:04:28 CST 2018
    doSomething
    Call-return time = 0msecs
    Time called somethingElse() 3 : 1536732268537 msecs
    on Wed Sep 12 14:04:28 CST 2018
    somethingElse bonobo
    Call-return time = 0msecs
    
    Time called doSomething() 4 : 1536732268537 msecs
    on Wed Sep 12 14:04:28 CST 2018
    doSomething
    Call-return time = 0msecs
    Time called somethingElse() 5 : 1536732268537 msecs
    on Wed Sep 12 14:04:28 CST 2018
    somethingElse bonobo
    Call-return time = 0msecs
    

    5.修改SimpleDynamicProxy.java 使其可以度量方法调用的次数

    package com.lhsjohn.typeinfo.prac;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Date;
    
    class DynamicProxyHandler2 implements InvocationHandler {
        private Object proxied;
        public DynamicProxyHandler2(Object proxied) {
            this.proxied = proxied;
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            long timeIn = new Date().getTime();
            System.out.println("**** proxy: " + proxy.getClass() +
                ", method: " + method + ", args: " + args +
                ", invoked at " + timeIn + " on " + (new Date()));
            if(args != null)
                for(Object arg : args)
                    System.out.println("  " + args);
            long timeOut = new Date().getTime();
            System.out.println("Method call-return time: " + (timeOut - timeIn) + " msecs");
            return method.invoke(proxied, args);        
        }
    }
    public class SimpleDynamicProxy22 {
        
        public static void consumer(Interface iface) {
            iface.doSomething();
            iface.somethingElse("bonobo");
        }
        public static void main(String[] args) {
            RealObject real = new RealObject();
            consumer(real);
            // Insert a proxy and call again:
            Interface proxy = (Interface)Proxy.newProxyInstance(
                Interface.class.getClassLoader(),
                new Class[]{ Interface.class },
                new DynamicProxyHandler2(real));
            consumer(proxy);        
        }
    }
    

    运行结果

    doSomething
    somethingElse bonobo
    **** proxy: class com.lhsjohn.typeinfo.prac.$Proxy0, method: public abstract void com.lhsjohn.typeinfo.prac.Interface.doSomething(), args: null, invoked at 1536732359159 on Wed Sep 12 14:05:59 CST 2018
    Method call-return time: 17 msecs
    doSomething
    **** proxy: class com.lhsjohn.typeinfo.prac.$Proxy0, method: public abstract void com.lhsjohn.typeinfo.prac.Interface.somethingElse(java.lang.String), args: [Ljava.lang.Object;@1540e19d, invoked at 1536732359176 on Wed Sep 12 14:05:59 CST 2018
      [Ljava.lang.Object;@1540e19d
    Method call-return time: 0 msecs
    somethingElse bonobo
    
    

    6.在SimpleDynamicProxy.java的invoke()内部,尝试打印proxy参数

    package com.lhsjohn.typeinfo.prac;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    class DynamicProxyHandler implements InvocationHandler {
        private Object proxied;
        public DynamicProxyHandler(Object proxied) {
            this.proxied = proxied;
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("**** proxy: " + proxy.getClass() +
                ", method: " + method + ", args: " + args);
            if(args != null)
                for(Object arg : args)
                    System.out.println("  " + args);
            return method.invoke(proxied, args);
        }
    }
    
    class SimpleDynamicProxy23 {
        public static void consumer(Interface iface) {
            iface.doSomething();
            iface.somethingElse("bonobo");
        }
        public static void main(String[] args) {
            RealObject real = new RealObject();
            consumer(real);
            Interface proxy = (Interface)Proxy.newProxyInstance(
                Interface.class.getClassLoader(),
                new Class[]{ Interface.class },
                new DynamicProxyHandler(real));
            consumer(proxy);        
        }
    }
    

    运行结果:

    doSomething
    somethingElse bonobo
    **** proxy: class com.lhsjohn.typeinfo.prac.$Proxy0, method: public abstract void com.lhsjohn.typeinfo.prac.Interface.doSomething(), args: null
    doSomething
    **** proxy: class com.lhsjohn.typeinfo.prac.$Proxy0, method: public abstract void com.lhsjohn.typeinfo.prac.Interface.somethingElse(java.lang.String), args: [Ljava.lang.Object;@28d93b30
      [Ljava.lang.Object;@28d93b30
    somethingElse bonobo
    
    

    作者:lhsjohn

    相关文章

      网友评论

          本文标题:Java的反射机制 (二)动态代理(仅供复习查阅)

          本文链接:https://www.haomeiwen.com/subject/nujihqtx.html