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

2018-12-13  本文已影响0人  lhsjohn

代理类在程序运行时创建的代理方式被成为动态代理。 也就是说,这种情况下,代理类并不是在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

上一篇下一篇

猜你喜欢

热点阅读