频道栏目
首页 > 程序开发 > 软件开发 > Java > 正文
动态代理(1)----JDK动态代理
2013-02-27 14:21:42           
收藏   我要投稿
Java的Java.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对象.

 

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

 

 

[java]  

//创建一个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 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});

 

 

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

 

 

[java]  

//创建一个InvocationHandler对象   

    InvocationHandler hanlder=new MyInvocationHandler(...);  

    //使用Proxy直接生成一个动态代理对象   

    Foo f=(Foo)Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[]{Foo.class},handler);  

 

//创建一个InvocationHandler对象

InvocationHandler hanlder=new MyInvocationHandler(...);

//使用Proxy直接生成一个动态代理对象

Foo f=(Foo)Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[]{Foo.class},handler);

 

 

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

 

 

[java] 

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;  

    }  

}  

 

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接口,该接口中包含了walk和sayHello两个抽象方法,接着程序定义了一个简单的InvocationHandler实现类,定义该实现类时需要重写invoke方法----执行代理对象所有方法执行时将会替换成执行此invoke方法. 

 

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

 

点击复制链接 与好友分享!回本站首页
相关TAG标签 动态
上一篇:Swinghacks——JTable根据内容调整列宽
下一篇:基于OSGi的企业级开发框架实践——OSGi Annotations
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站