• 动态代理(1)JDK动态代理


    JavaJava.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成JDK动态代理类或动态代理对象.

    Proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类.如果我们在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类:如果需要为一个或多个接口动态的创建实例,也可以使用Proxy类创建动态代理实例.

    Proxy提供了如下两个方法来创建动态代理类和动态代理实例:

    1.  staticClass<?>getProxyClass(ClassLoader loader,Class <?>...interfaces):创建一个动态代理类所对应的Class对象,该代理类将实现interfaces所指定的多个接口.第一个ClassLoader指定生成动态代理类的类加载器.

    2.  staticObject newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler):直接创建一个动态代理对象,该代理对象的实现类实现了interfaces指定的系列接口,执行代理对象的每个方法时都会被替代执行InvocationHandler对象的invoke方法.

    实际上,即使采用第一种方法获取了一个动态代理类之后,当程序需要通过该代理类来创建对象时一样需要传入一个InvocationHandler对象.也就是说,系统生成的每一个代理对象都有一个与之关联的InvocationHandler对象.

    程序中生成动态代理对象可以采用先生成一个动态代理类,然后通过动态代理类来创建对象的方式来生成一个动态代理对象.如下代码片段

    //创建一个InvocationHandler对象
    	InvocationHandler handler=new MyInvocationHandler(...);
    	//使用Proxy生成一个动态代理类proxyClass
    	Class proxyClass=Proxy.getProxyClass(Foo.class.getClassLoader(),new Class[]{Foo.class});
    	//获取proxyClass类中带一个InvocationHandler参数的构造器
    	Constructor<T> ctor =proxyClass.getConstructor(new Class[]{InvocationHandler.class});
    	//调用ctor的newInstance方法来创建动态实例
    	Foo f=(Foo)ctor.newInstance(new Object[]{handler});

    上面代码可以简化成如下代码

    //创建一个InvocationHandler对象
    	InvocationHandler hanlder=new MyInvocationHandler(...);
    	//使用Proxy直接生成一个动态代理对象
    	Foo f=(Foo)Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[]{Foo.class},handler);

    下面程序示范了使用ProxyInvocationHandler来生成动态代理对象

    public class ProxyTest {
    	public static void main(String[] args) throws Exception{
    		//创建一个InvocationHandler对象
    		InvocationHandler handler=new MyInvokationHandler();
    		//使用指定的InvocationHanlder来生成一个动态代理对象
    		PersonPro p=(PersonPro)Proxy.newProxyInstance(PersonPro.class.getClassLoader(), new Class[]{PersonPro.class}, handler);
    		//调用动态代理对象的walk()方法和sayHello()方法
    		p.walk();
    		p.sayHello("luck");
    	}
    }
    interface PersonPro{
    	void walk();
    	void sayHello(String name);
    }
    class MyInvokationHandler implements InvocationHandler{
    	/*
    	 * 执行动态代理对象的所有方法时,都会被替换成执行如下invoke方法
    	 * 其中:
    	 * proxy--代表动态代理对象
    	 * method--代表正在执行的方法
    	 * args--代表执行代理对象方法时传入的实参
    	 */
    	public Object invoke(Object proxy,Method method,Object[] args){
    		System.out.println("正在执行的方法:"+method);
    		if(args!=null){
    			System.out.println("下面是执行该方法时传入的实参:");
    			for(Object val:args){
    				System.out.println(val);
    			}
    		}else{
    			System.out.println("调用该方法无须实参");
    		}
    		return null;
    	}
    }

    上面程序中提供了一个Person接口,该接口中包含了walksayHello两个抽象方法,接着程序定义了一个简单的InvocationHandler实现类,定义该实现类时需要重写invoke方法----执行代理对象所有方法执行时将会替换成执行此invoke方法.

    从运行结果中可以看出,不管程序执行代理对象的walk()方法,还是执行代理对象的sayHello()方法,实际上都是执行InvocationHandler对象的invoke()方法.

    下一篇文章将实现SpringAOP的动态代理的demo.

  • 相关阅读:
    日期型数据知识
    如何让VS检查函数和类Comment的添加情况
    HTTP request is unauthorized with client authentication scheme 'Anonymous'.
    将SerializableAttribute序列化为xml
    使用EnterpriseLibrary Validation Block对WCF做验证
    表达式树中递归方法
    使用SignalR在Asp.net中实现进度条
    SQLServer中列出数据库的所有表的创建时间
    用Knockoutjs与Asp.net MVC实现级联下拉列表
    使用UnityAutoMoq简化单元测试
  • 原文地址:https://www.cnblogs.com/beijiguangyong/p/2966596.html
Copyright © 2020-2023  润新知